KMP,Trie,&&洛谷P2580
作者:互联网
KMP:
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e6+5; 4 char a[maxn],b[maxn],aa[maxn],bb[maxn]; 5 //aa,bb为输入的字符串 6 //为了方便KMP的实现 7 //另开a,b两个字符串为实际操作自符串 8 //b为模式串 9 int nxt[maxn],cx[maxn]; 10 //nxt【i】为b中以下标 i结尾“非前缀”的子串中 11 //与前缀相同的最大长度 12 int main(){ 13 cin>>aa>>bb; 14 int la=strlen(aa); 15 int lb=strlen(bb); 16 for(int i=0;i<la;i++)a[i+1]=aa[i];//使首字母下标为1 17 for(int i=0;i<lb;i++)b[i+1]=bb[i];//同上 18 int j=0; 19 for(int i=2;i<=lb;i++){//nxt非前缀,i从2开始枚举 20 while(j>0&&b[i]!=b[j+1])j=nxt[j]; 21 //无法继续匹配,j缩小至nxt【j】 22 if(b[i]==b[j+1])j++; 23 nxt[i]=j; 24 } 25 j=0;//初始化 26 for(int i=1;i<=la;i++){ 27 //a与b匹配,无非前缀要求,i从一开始枚举 28 while(j>0&&(j==lb||a[i]!=b[j+1]))j=nxt[j]; 29 if(a[i]==b[j+1])j++; 30 cx[i]=j; 31 if(cx[i]==lb){ 32 // 连续出现最大长度 等于b长度 33 //b在a中出现一次,以i结尾 34 printf("%d\n",i-j+1); 35 } 36 } 37 for(int i=1;i<=lb;i++){ 38 printf("%d ",nxt[i]); 39 } 40 return 0; 41 }
Trie(字典树):
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e5+5; 4 char str[maxn]; 5 int n; 6 int son[maxn][30],cnt[maxn],idx; 7 void insert(char str[]){ 8 int p=0; 9 for(int i=0;str[i];i++){ 10 int u=str[i]-'a'; 11 if(!son[p][u])son[p][u]=++idx; 12 p=son[p][u]; 13 } 14 cnt[p]++; 15 } 16 int question(char str[]){ 17 int p=0; 18 for(int i=0;str[i];i++){ 19 int u=str[i]-'a'; 20 if(!son[p][u])return 0; 21 p=son[p][u]; 22 } 23 return cnt[p]; 24 } 25 int main(){ 26 scanf("%d",&n); 27 while(n--){ 28 char op[2]; 29 scanf("%s%s",&op,&str); 30 if(op[0]=='I')insert(str); 31 else 32 printf("%d\n",question(str)); 33 } 34 return 0; 35 }
没来得及写注释,下次一定,回头补一下
洛谷P2580于是他错误的点名开始了
由判断一个字符串出现几次变为判断字符串是否出现,需要加特判,不然最后一个Hash毒瘤数据会被卡(但是被卡了也显示我是100,只不过不是Accept
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn=2000005; 4 int n,m,son[maxn][30],cnt[2000005],idx; 5 char str[maxn]; 6 bool vis[2000005]; 7 void insert(char str[]){ 8 int p=0; 9 for(int i=0;str[i];i++){ 10 int u=str[i]-'a'; 11 if(!son[p][u])son[p][u]=++idx; 12 p=son[p][u]; 13 } 14 cnt[p]=1; 15 } 16 void find(char str[]){ 17 int p=0; 18 for(int i=0;str[i];i++){ 19 int u=str[i]-'a'; 20 if(!son[p][u]){ 21 printf("WRONG\n"); 22 return ; 23 } 24 p=son[p][u]; 25 } 26 if(vis[p]==1){ 27 printf("REPEAT\n"); 28 return ; 29 } 30 else if(cnt[p]){ 31 vis[p]=1; 32 printf("OK\n"); 33 return ; 34 } 35 printf("WRONG\n"); 36 } 37 int main(){ 38 scanf("%d",&n); 39 for(int i=1;i<=n;i++){ 40 scanf("%s",str); 41 insert(str); 42 } 43 scanf("%d",&m); 44 for(int i=1;i<=m;i++){ 45 scanf("%s",str); 46 find(str); 47 } 48 return 0; 49 }
同样没来得及写注释
姑且先记录一下
//我曾难自拔于世界之大
//也沉溺于其中梦话
//不得真假,不做挣扎,不惧笑话
//我曾将青春翻涌成她
//也曾指尖弹出盛夏
//心之所动,就随风去吧
//---《起风了》
愿我们能一直勇敢下去
标签:洛谷,P2580,Trie,++,son,char,int,maxn,str 来源: https://www.cnblogs.com/TFLSc1908lzs/p/16690308.html