ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

D K匹配 kmp 区间匹配计算贡献

2022-09-12 18:31:38  阅读:192  来源: 互联网

标签:nxt 匹配 SSS TTT leq 字符串 kmp 区间


 链接:https://ac.nowcoder.com/acm/problem/213329
来源:牛客网

题目描述

牛牛是赫赫有名的字符串高手,现在牛牛发现了一种新的匹配方式。给定一个字符串SSS和一个字符串TTT,如果SSS存在一个长度为kkk的子串Sl1,l1+k−1S_{l_1, l_1 + k - 1}Sl1​,l1​+k−1​和TTT的某个长度为kkk的子串Tl2,l2+k−1T_{l_2,l_2 + k - 1}Tl2​,l2​+k−1​相等,那么我们就认为字符串SSS和字符串TTT是kkk匹配的。比如字符串abaccabaccabacc和字符串ddabackkddabackkddabackk就是444匹配的。 牛牛知道这种匹配方式之后就迫不及待的想要提出新的问题。给定一个长度为nnn的字符串SSS和一个长度为kkk的字符串TTT,现在牛牛想知道SSS有多少个子串和TTT是满足kkk匹配的。 本场大样例下载

输入描述:

第一行两个整数n,kn, kn,k分别表示字符串SSS的长度和字符串TTT的长度。 第二行一个长度为nnn的字符串表示SSS。 第三行一个长度为kkk的字符串表示TTT。 保证字符串SSS和TTT中只包含小写字母。

输出描述:

输出一行整数表示SSS中满足和TTT是kkk匹配的子串个数。
示例1

输入

复制
10 2
abaaaababa
ab

输出

复制
33

备注:

对于20%20 \%20%的数据满足1≤k≤n≤5001 \leq k \leq n \leq 5001≤k≤n≤500 对于40%40\%40%的数据满足1≤k≤n≤50001 \leq k \leq n \leq 50001≤k≤n≤5000 对于60%60\%60%的数据满足1≤k≤n≤1e61 \leq k \leq n \leq 1e61≤k≤n≤1e6 对于100%100\%100%的数据满足1≤k≤n≤1e71 \leq k \leq n \leq 1e71≤k≤n≤1e7

分析:

明确题意 k 匹配,是指匹配串在主串的某个子串中被匹配。

所以只要找到每个子串匹配的起点

[i,j] 区间内被匹配,[1,i],[j,n] 区间内的子串也能匹配匹配串

注意当前匹配的子串可能跟上一次被匹配的子串重复,所以左区间从上次匹配的位置i'开始 [i',i],[j,n] 区间内匹配

注意第一次被匹配,上一次被匹配的位置应该是 0,只要插入一个0就可以了

//-------------------------代码----------------------------

//#define int ll
const int N = 1e7+10;
int n,k;
string s,t;
int nxt[N];

void solve()
{
//    cin>>n>>m;
    cin>>n>>k;;
    cin>>s>>t;
    int lens = s.length(),lent = t.length();
    s = ' ' + s;t = ' ' + t;
    fo(i,2,k) {
        nxt[i] = nxt[i-1];
        while(nxt[i] && t[nxt[i] + 1] != t[i]) nxt[i] = nxt[nxt[i]];
        nxt[i] += (t[nxt[i] + 1] == t[i]);
    }
    V<int> q;
    int j = 1;
    q.push_back(0);
    fo(i,1,n) {
        while(j != 1 && s[i] != t[j])j = nxt[j - 1] + 1;
        if(s[i] == t[j]) j ++ ;
        if(j == lent + 1) {
            q.pb(i - lent + 1);
            j = nxt[j - 1] + 1;
        }
    }
    ll ans = 0;
    int len = q.size() - 1;
//     db(len)
    for(int i = 1;i<=len;i++) {
        int ll = q[i-1],l = q[i];
        int r = l + lent - 1;
//         dbbb(ll,l,r);
        ans += 1ll * (l - ll) * (n - r + 1);
    }
    cout<<ans<<endl;
}

void main_init() {}
signed main(){
    AC();clapping();TLE;
    cout<<fixed<<setprecision(12);
    main_init();
//  while(cin>>n,n)
//  while(cin>>n>>m,n,m)
//    int t;cin>>t;while(t -- )
    solve();
//    {solve(); }
    return 0;
}

/*样例区


*/

//------------------------------------------------------------

 

标签:nxt,匹配,SSS,TTT,leq,字符串,kmp,区间
来源: https://www.cnblogs.com/er007/p/16686956.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有