【KMP】合并字符串

输入N个字符串,S1...Sn,表示字符串集合S

 给你N个字符串组成的集合S,然后,让你从S中选出若干个字符串,组成新的集合T,

对于S中的每一个字符串Si,都能够在T中找到一个字符串Ti,使得Si是Ti的子串、

 要求组成新的字符串集合T的元素个数要最少、

然后,让你按照之前输入的顺序,输出T集合中的字符串、

(N<1000,每个字符串的长度最大为1000)

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 #include <algorithm>
 5 using namespace std;
 6 struct Str{
 7     char Str[2010];
 8     int Next;//记录下一个字符串的编号
 9     int Fa;//记录上一个字符串的编号
10 }ID[10086];
11 int Len;
12 void getNext(char p[],int next[],int Len_t)
13 {
14     int i=0,j=-1;
15     next[0]=-1;
16     while(i<Len_t){
17         if(j==-1||p[i]==p[j])next[++i]=++j;
18         else j=next[j];
19     }
20 }
21 int KMPMatch(char s[],char p[])
22 {
23     int next[200005];
24     int i=0,j=0,sign=0;
25     int Len_t=strlen(p),Len_S=strlen(s);
26     getNext(p,next,Len_t);
27     while(i<Len_S)
28     {
29         if(j==-1||s[i]==p[j]){i++;j++;}
30         else j=next[j];
31         if(j==Len_t) return i-Len_t+1;
32     }
33     return -1;    /*返回值是子串在主串第一个匹配的起始位置*/
34 }
35 int main()
36 {
37     int T,i,j,Ans,N,t=1;
38     scanf("%d",&T);
39     while(T--){
40         scanf("%d",&N);Ans=1;
41         ID[0].Next=1;
42         for(i=1;i<=N;i++){
43             scanf(" %s",ID[i].Str);
44             ID[i].Next=i+1;ID[i].Fa=i-1;
45         }
46         for(i=2;i<=N;i++){//合并字符串
47             int TMD=ID[i].Fa;
48             if(!TMD)continue;
49             if(KMPMatch(ID[i].Str,ID[TMD].Str)!=-1){
50                 ID[i].Fa=ID[TMD].Fa;
51                 ID[ID[TMD].Fa].Next=i;
52                 i--;
53             }
54         }
55         printf("Case #%d:\n",t++);
56         for(i=ID[0].Next;i<=N;i=ID[i].Next){
57             printf("%s\n",ID[i].Str);
58         }
59     }
60     return 0;
61 }
View Code

 

posted @ 2016-04-20 21:52  Wurq  阅读(168)  评论(0编辑  收藏  举报