字符串截取模板 && POJ 34503080 ( 暴力枚举子串 && KMP匹配 )
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了字符串截取模板 && POJ 34503080 ( 暴力枚举子串 && KMP匹配 )相关的知识,希望对你有一定的参考价值。
//截取字符串 ch 的 st~en 这一段子串返回子串的首地址 //注意用完需要根据需要最后free()掉 char* substring(char* ch,int st,int en) { int length = en - st + 1; char* pch=ch; char* subch=(char*)malloc(length+1); pch=pch+st; for(int i=0;i<length;i++) subch[i]=*(pch++); subch[length]=‘\0‘; return subch; }
题意 : 给出 n 个包含 60 个字符的字符串,问你这 n 个字符串的最长公共子串是什么,如果有多个,输出字典序最小的,如若没有则输出 “no significant commonalities”
分析 : 直接选择第一个串然后从长到短截取各个长度的子串去跟剩下的 n-1 个串进行匹配,如果得以匹配则比较这个长度下的其他未枚举的子串,选出字典序最小的继续匹配,持续更新答案,最后输出即可。
#include<string.h> #include<stdio.h> #include<string> #include<malloc.h> #include<stdlib.h> using namespace std; const int maxn = 60 + 5; char str[10][maxn], fir[maxn]; char * mo, * ans; int num, Next[maxn], moL; char* substring(char* ch,int st,int en) { int length = en - st + 1; char* pch=ch; char* subch=(char*)malloc(length+1); pch=pch+st; for(int i=0;i<length;i++) subch[i]=*(pch++); subch[length]=‘\0‘; return subch; } inline void GetNext() { int i = 0, j = -1; Next[i] = j; while(i < moL){ while(j!=-1 && mo[i]!=mo[j]) j = Next[j]; Next[++i] = ++j; } } bool KmpCount(int who) { int i = 0, j = 0; while(j < moL && i < 60){ while(j!=-1 && mo[j]!=str[who][i]) j = Next[j]; i++, j++; } if(j == moL) return true; return false; } bool Is_Match(int st, int en) { moL = en - st + 1; mo = substring(fir, st, en); GetNext(); for(int k=1; k<num; k++){ if(!KmpCount(k)) return false; }return true; } inline void Find_better_ans(int pos, int len, int en) { for(int i=pos+1; i<=en; i++){ for(int k=0,j=i; j<=i+len; j++,k++){ if(ans[k] > fir[j]){ if(Is_Match(i, i+len)){ ans = substring(mo, 0, moL-1); }else { free(mo); break; } }else if(ans[k] < fir[j]) break; } } } bool Have_ans() { for(int len=59; len>=1; len--){///枚举截取子串的长度,从大到小枚举 for(int i=0; i<=59-len; i++){///在这个长度下,枚举所有子串的首字母 if(Is_Match(i, i+len)){///判断是否匹配 ans = substring(mo, 0, moL-1); Find_better_ans(i, len, 59-len); return true; }else free(mo); } }return false; } int main(void) { int nCase; scanf("%d", &nCase); while(nCase--){ scanf("%d", &num); scanf("%s", fir); for(int i=1; i<num; i++) scanf("%s", str[i]); if(Have_ans()) { puts(ans); free(ans); } else puts("no significant commonalities"); } return 0; }
题意 : 给出 n 个字符串,问你最长的公共子串,没有则输出 “IDENTITY LOST”
分析 : 这次直接选一个最短的,枚举其所有的子串去匹配剩下的 n-1 个串即可
#include<stdio.h> #include<string.h> #include<malloc.h> #include<algorithm> const int maxn = 4050; char StrGroup[maxn][maxn], str[maxn], *mo, *ans; int moL, Next[maxn], num, MinL, index, Len[maxn]; char* substring(int st,int en) { int length = en - st + 1; char* subch=(char*)malloc(length+1); for(int i=0,j=st;i<length;j++,i++) subch[i]=StrGroup[index][j]; subch[length]=‘\0‘; return subch; } inline void GetNext() { int i = 0, j = -1; Next[i] = j; while(i < moL){ while(j!=-1 && mo[i]!=mo[j]) j = Next[j]; Next[++i] = ++j; } } bool RunKmp(int who) { int i = 0, j = 0; while(j < moL && i < Len[who]){ while(j!=-1 && mo[j]!=StrGroup[who][i]) j = Next[j]; i++, j++; } if(j == moL) return true; return false; } bool RunMatch() { GetNext(); for(int i=1; i<=num; i++){ if(i!=index){ if(!RunKmp(i)) return false; } }return true; } inline void Find_Better_Ans(int st, int len) { for(int i=st+1; i<=MinL-len; i++){ for(int j=i,k=0; k<len; j++,k++){ //printf("ok %s\n", ans); if(ans[k] > StrGroup[index][j]){ mo = substring(i, i+len-1); moL = strlen(mo); if(RunMatch()){ free(ans); ans = mo; break; }else{ free(mo); break; } }else if(ans[k] < StrGroup[index][j]) break; } } } bool Match(int len) { for(int i=0; i<=MinL-len; i++){ moL = len; mo = substring(i, i+len-1); if(RunMatch()){ ans = mo; Find_Better_Ans(i, len); return true; }else free(mo); }return false; } inline void PrintAns() { for(int len=MinL; len>0; len--) if(Match(len)){ puts(ans); free(ans); return; } puts("IDENTITY LOST"); } int main(void) { while(~scanf("%d", &num) && num){ MinL = 0x3f3f3f3f; for(int i=1; i<=num; i++){ scanf("%s", StrGroup[i]); Len[i] = strlen(StrGroup[i]); if(MinL > Len[i]){ MinL = Len[i]; index = i; } }PrintAns(); } return 0; }
以上是关于字符串截取模板 && POJ 34503080 ( 暴力枚举子串 && KMP匹配 )的主要内容,如果未能解决你的问题,请参考以下文章
POJ 1845-Sumdiv 数论 +快速幂&&筛素&&分解质因数&&求因数之和的模板