题意:给你一个模式串和一堆长度相同的不相同的匹配串,问是否有一个方案可以让这个模式串由这些匹配串首尾相连组成,每个串只能出现一次.

思路:还是比较简单的,显然模式串每个位置最多匹配一个匹配串,因为所有的匹配串严格不同,每个位置有没有匹配哪个匹配串用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\n");
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\n");
147     return 0;
148 }