输入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 }