算法模版:KMP及字符串经典模拟
前言
唤我沈七就好啦。
字符串
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
olleh dlrow
#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以上就是对 算法模版:数论之约数全家桶 的全部讲解啦,很感谢你能看到这儿。如果有遗漏、错误或者有更加通俗易懂的讲解,欢迎小伙伴私信我,我后期再补充完善。