题意:给你一个模式串和一堆长度相同的不相同的匹配串,问是否有一个方案可以让这个模式串由这些匹配串首尾相连组成,每个串只能出现一次.
思路:还是比较简单的,显然模式串每个位置最多匹配一个匹配串,因为所有的匹配串严格不同,每个位置有没有匹配哪个匹配串用ac自动机很容易就能跑出来,然后枚举一下位置就ok,还有模式串应该在开头加上尾部的一些字符,因为要求的是这个模式串要看成一个环.
1 #include <bits/stdc++.h> 2 using namespace std; 3 char aim[2000010]; 4 int pos[2000010]; 5 char temp[100010]; 6 int total; 7 struct Root 8 { 9 Root *next[26]; 10 int count; 11 Root *fail; 12 Root() 13 { 14 for(int i=0; i<26; i++) 15 next[i]=NULL; 16 fail=NULL; 17 count=0; 18 } 19 }; 20 queue<Root *>q; 21 class AC_auto 22 { 23 public: 24 AC_auto(); 25 void insert(char object[],int num); 26 void ac_auto(); 27 void match(char aim[]); 28 private: 29 Root *root; 30 }; 31 AC_auto::AC_auto() 32 { 33 root=new Root(); 34 } 35 void AC_auto::insert(char object[],int num) 36 { 37 int len=strlen(object); 38 Root *temp=root; 39 for(int i=0; i<len; i++) 40 { 41 if(temp->next[object[i]-'a']==NULL) 42 { 43 Root *temp1=new Root(); 44 temp->next[object[i]-'a']=temp1; 45 } 46 temp=temp->next[object[i]-'a']; 47 } 48 temp->count=num; 49 } 50 void AC_auto::ac_auto() 51 { 52 while(!q.empty())q.pop(); 53 q.push(root); 54 Root *temp1,*temp2; 55 while(!q.empty()) 56 { 57 temp1=q.front(); 58 q.pop(); 59 for(int i=0; i<26; i++) 60 { 61 if(temp1->next[i]) 62 { 63 if(temp1==root) 64 temp1->next[i]->fail=root; 65 else 66 { 67 temp2=temp1->fail; 68 while(temp2) 69 { 70 if(temp2->next[i]) 71 { 72 temp1->next[i]->fail=temp2->next[i]; 73 break; 74 } 75 temp2=temp2->fail; 76 } 77 if(temp2==NULL) 78 temp1->next[i]->fail=root; 79 } 80 q.push(temp1->next[i]); 81 } 82 } 83 } 84 } 85 void AC_auto::match(char aims[]) 86 { 87 int len=strlen(aims); 88 Root *temp1,*temp=root; 89 for(int i=0; i<len; i++) 90 { 91 if(aims[i]>'z'||aims[i]<'a') 92 { 93 temp=root; 94 continue; 95 } 96 while(temp->next[aims[i]-'a']==NULL&&temp!=root) 97 temp=temp->fail; 98 temp=temp->next[aims[i]-'a']; 99 if(!temp)temp=root; 100 if(temp->count) 101 pos[i]=temp->count; 102 } 103 } 104 bool sign[100010]; 105 int main() 106 { 107 int n,k; 108 scanf("%d%d",&n,&k); 109 scanf("%s",aim+k); 110 for(int i=0;i<k;i++) 111 aim[i]=aim[(n+1)*k-k+i]; 112 AC_auto *ac_auto=new AC_auto(); 113 int g; 114 scanf("%d",&g); 115 for(int i=1;i<=g;i++) 116 { 117 scanf("%s",temp); 118 ac_auto->insert(temp,i); 119 } 120 ac_auto->ac_auto(); 121 ac_auto->match(aim); 122 for(int i=k;i<2*k;i++) 123 { 124 for(int j=i;j<n*k+k;j+=k) 125 { 126 if(pos[j]==0) 127 break; 128 else if(sign[pos[j]]) 129 break; 130 sign[pos[j]]=true; 131 if(j+k>=n*k+k) 132 { 133 printf("YES "); 134 for(int j=i;j<n*k+k;j+=k) 135 printf("%d ",pos[j]); 136 return 0; 137 } 138 } 139 for(int j=i;j<n*k+k;j+=k) 140 { 141 if(pos[j]==0) 142 break; 143 sign[pos[j]]=false; 144 } 145 } 146 printf("NO "); 147 return 0; 148 }