https://www.bnuoj.com/v3/external/gym/101241.pdf
【题意】
- 给定n个字符串,大小写敏感
- 定义一个操作:选择任意m个串首尾相连组成一个新串
- 问是否存在一个这样的串s,s可以由不同的串首尾相连得到
- 最多100个字符串,所有字符串的总长度不超过5000
【样例解释】
aB5可以由a+B5得到,也可以由aB+5得到,所以输出YES
【思路】
- 首先一定是在100个选择2个串a,b,a是b的前缀
- 然后a和b的前缀可以消去,我们想知道b剩下的右半部分是哪一个串的前缀
- 找到这个串后前缀也可以消去,然后再找剩下的部分
- 因为数据范围不是很大,所以可以暴力搜索,bfs 700ms过
- vis[i][j]在bfs中去重,代表是i字符串的以j开始的后缀
【AC】
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 #include<queue> 7 8 using namespace std; 9 int n; 10 const int maxn=5e4+2; 11 char str[102][maxn]; 12 int len[102]; 13 int flag; 14 bool vis[102][maxn]; 15 struct node 16 { 17 int id; 18 int len; 19 node(){} 20 node(int _id,int _len):id(_id),len(_len){} 21 }; 22 bool solve() 23 { 24 queue<node> Q; 25 for(int i=0;i<n;i++) 26 { 27 for(int j=0;j<i;j++) 28 { 29 int l=min(len[i],len[j]); 30 int tot=0; 31 for(int k=0;k<l;k++) 32 { 33 if(str[i][k]==str[j][k]) tot++; 34 else break; 35 } 36 if(tot!=l) continue; 37 if(len[i]==len[j]) return true; 38 if(len[i]<len[j]) 39 { 40 vis[j][len[i]]=true; 41 Q.push(node(j,len[i])); 42 } 43 else 44 { 45 vis[i][len[j]]=true; 46 Q.push(node(i,len[j])); 47 } 48 } 49 } 50 while(!Q.empty()) 51 { 52 node q=Q.front(); Q.pop(); 53 for(int i=0;i<n;i++) 54 { 55 int lq=len[q.id]-q.len; 56 int l=min(lq,len[i]); 57 int tot=0; 58 for(int j=0;j<l;j++) 59 { 60 if(str[i][j]==str[q.id][q.len+j]) tot++; 61 else break; 62 if(tot==l) 63 { 64 if(lq==len[i]) return true; 65 else if(lq<len[i]) 66 { 67 if(!vis[i][lq]) 68 { 69 vis[i][lq]=true; 70 Q.push(node(i,lq)); 71 } 72 } 73 else 74 { 75 if(!vis[q.id][q.len+len[i]]) 76 { 77 vis[q.id][q.len+len[i]]=true; 78 Q.push(node(q.id,q.len+len[i])); 79 } 80 } 81 82 } 83 } 84 } 85 } 86 return false; 87 } 88 int main() 89 { 90 freopen("input.txt","r",stdin); 91 freopen("output.txt","w",stdout); 92 scanf("%d",&n); 93 for(int i=0;i<n;i++) 94 { 95 scanf("%s",str[i]); 96 len[i]=strlen(str[i]); 97 } 98 if(solve()) 99 { 100 puts("YES"); 101 } 102 else 103 { 104 puts("NO"); 105 } 106 return 0; 107 }