前言
唤我沈七就好啦。
字符串
KMP:高效查找子串
ne[j] 作用:记录模式串中 j 之前的最长的相等前后辍 这样当出现不匹配的时候后 可以直接跳转到 以前一个字符 结尾的 公共最长前后辍 的前缀 的后面 例如下面这个例子 s: abbabfab p: abbabc 当前位置时 s串的'f'与p串的'c'不匹配 kmp的思想是:跳转到 以'c'前面的'b'字符结尾的 公共最长前后辍 的 前缀 的后面 即 前缀 ab 后面 'b'位置 s: abbabfab p: abbabc
#include<bits/stdc++.h> using namespace std; const int N = 1e7+10; int n,m; int ne[N]; char s[N],p[N]; int main() { cin>>s+1>>p+1; n=strlen(s+1),m=strlen(p+1); 生成 ne【】数组 ,这里利用了动态规划的思想 for(int i =2 , j = 0 ; i <= m ; i ++) { while(j&&p[i]!=p[j+1])j=ne[j]; if(p[i]==p[j+1])j++; ne[i]=j; } 利用ne【】数组,增强匹配效率 for(int i = 1 , j = 0; i <= n ; i ++) { while(j&&s[i]!=p[j+1])j=ne[j]; if(s[i]==p[j+1])j++; if(j==m) { printf("%d\n",i-m+1); j=ne[j]; } for(int i = 1 ; i <= m ; i ++) printf("%d ",ne[i]); }
如果读者读到现在对 KMP 的实现原理还是一头雾水,我的建议是 背。
当然 背模板的前提是你最起码 已经 ne【】数组的含义了,至于生成 ne【】数组的过程。
如果你实在对其原理感兴趣 ,可以访问网站 AcWing,那里会有对KMP的讲解 。
验证子串(暴力解法)
#include<bits/stdc++.h> using namespace std; const int N = 1e7+10; int n,m; int ne[N]; char s[N],p[N]; void kmp(int n,string a,string b) { for(int i = 0 ; i < n ; i ++) { int j = 0 ,k=i; while(a[k++]==b[j++]&&a[k-1]!=0)continue; if(j==b.size()+1) { cout<<b+" is substring of "+a; return ; } } cout<<"No substring"; return ; } int main() { string a,b; cin>>a>>b; if(a.size()>b.size()) kmp(a.size(),a,b); else kmp(b.size(),b,a); }
字符串经典模拟
删除字符后辍
给定一个单词,如果该单词以er、ly或者ing后缀结尾,则删除该后缀(题目保证删除后缀后的单词长度不为0), 否则不进行任何操作。
将后辍的首字母设成 ‘\0’ 这样就不会打印后辍部分了
#include<stdio.h> #include<string.h> int main() { int i,j,m,n; char a[100]; gets(a); n=strlen(a); if(a[n-2]=='e'&&a[n-1]=='r') a[n-2]=0; else if(a[n-3]=='i'&&a[n-2]=='n'&&a[n-1]=='g') a[n-3]=0; else if(a[n-2]=='l'&&a[n-1]=='y') a[n-2]=0; printf("%s",a); return 0; }
最长最短单词
给定一句英文句子找出最长与最短的单词。
用
while(cin>>a)
输入数据 需要
按 Ctrl + Z + 回车
#include<bits/stdc++.h> using namespace std; int ans,cnt=99999; int main() { string a,b,c; while(cin>>a) { if(a.size()>ans) { b=a; ans=a.size(); } if(a.size()<cnt) { c=a; cnt=a.size(); } } cout<<b<<"\n"<<c; return 0; }
翻转单词
输入一个句子(一行),将句子中的每一个单词翻转后输出。
hello world
hello world
#include<bits/stdc++.h> using namespace std; int main() { string a,b; getline(cin,a); for(int i = 0; i <= a.size(); i ++) { if(a[i]==' '||a[i]==0) { for(int j = i-1;a[j]!=' '&&j>=0; j --) cout<<a[j]; cout<<" "; } } return 0; }
完结散花
ok以上就是对 算法模版:数论之约数全家桶 的全部讲解啦,很感谢你能看到这儿。如果有遗漏、错误或者有更加通俗易懂的讲解,欢迎小伙伴私信我,我后期再补充完善。
参考文献
https://www.acwing.com/activity/content/19/