刷题刷到kmp了 TLE了 想着还是sunday算法高效一点 还好写
kmp和扩展kmp的思想都是在不匹配时如何高效移动原串的匹配起点
sunday直接判断步长为模式串的长度,效率最高
原串 s:fffsffkfsfff size n=12 匹配起点为i
模式串 p:fsf size m=3
每次匹配 s从i开始 p从0开始
if 匹配成功则记录,i转到下一位置
判断第i+m位,找该位字母在p中最后出现的位置k
if 存在 i移到 i+m-k 位
else i移到 i+m+1 位
e.g. i=0
fffsffkfsfff
fsf
^
该位不匹配, i跳到 i+m = 3, s[3]=s, 在p中位置为k=1,i跳到i+m-k =2(其实就是转到长度一样的起点去判断
fffsffkfsfff
fsf
^
好了匹配成功
判断模式串每个字母最后出现位置用数组nex[ ]记录,遍历一遍p,更新就好,
nex初始化为-1, 这样 就一起解决原串中字母在模式串中找不到时i往后移一位的问题了 (i+m -k i+m-(-1) 模式串中存在则位置更新,否则记为-1
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<cstring> #include<string> #include<algorithm> #include<map> #include<queue> #include<stack> #include<list> #include<set> using namespace std; typedef long long ll; typedef pair<ll,ll> P; typedef pair<char,char> Pc; typedef long double ld; #define mem(x) memset(x, 0, sizeof(x)) #define me(x) memset(x, -1, sizeof(x)) #define fo(i,n) for(ll i=0; i<n; i++) #define sc(x) scanf("%lf", &x) #define pr(x) printf("%lld\n", x) #define pri(x) printf("%lld ", x) #define lowbit(x) x&-x const ll MOD = 1e9+7; const ll oo = 0x3f3f3f3f; const ll N = 2e6 +5; char a[N]; ll nex[100]; void getnext(string s) { me(nex); ll i, n=s.size(); for(i=0; i<n; i++) nex[s[i]-'a']=i; } void Sunday(string s, string p) { ll n=s.size(), m=p.size(); getnext(p); for(ll i=0; i<m; i++) cout<<nex[p[i]-'a']<<" ";cout<<endl; ll i=0, j, k, t; while(i<=n-m) { j=i; k=0; while(j<n && k<m && s[j]==p[k]) j++, k++; if(k==m) cout<<"match in pos"<<i<<endl; if(i+m<n) i+=(m-nex[s[i+m]-'a']); else {cout<<"not match"<<endl;return ;} } } int main() { ll i, j, k, l=0; ll n, m, t; string s, p; while(cin>>s>>p) { Sunday(s,p); cout<<endl; } return 0; }