Next数组应用

Simpsons’ Hidden Talents HDU—2594

题意:每组数据给出两个字符串 s1、s2,判断是否存在 s1 的前缀是 s2 的后缀的情况,若没有则输出 0,若有则输出这个前缀/后缀与其长度
思路:利用strcat函数将两个串和成一个串,最后Next[len]即为所求。要注意最长前缀后缀不能大于两个子串的长度len1,len2。

#include <iostream>
#include <algorithm>
#include <cmath>
#include <ctype.h>
#include <cstring>
#include <cstdio>
#include <sstream>
#include <cstdlib>
#include <iomanip>
#include <string>
#include <queue>
#include <map>

using namespace std;
const int maxn=1e6+10;
int Next[maxn];

void getNext(char w[],int m)//递推next数组
{
    int i=0,j=-1;
    memset(Next,0,sizeof(Next));
    Next[0]=-1;;
    while(i<m)
    {
        if(j==-1||w[i]==w[j])
            Next[++i]=++j;
        else
        {
            j=Next[j];
        }
    }
}
/*bool kmp(char w[],int m,char s[],int n)//w模板串,m模板串长度,s目标串,n目标串长度
{
    int i=0,j=0;
    getNext(w,m);
    while(i<n)
    {
        if(j==-1||w[j]==s[i])
            i++,j++;
        else
            j=Next[j];
        if(j>=m)
        {
            return true;
        }
    }
    return false;
}*/

int main()
{
   char a[maxn],b[maxn];
   while(~scanf("%s%s",a,b))
   {
       int len1=strlen(a);
       int len2=strlen(b);
       strcat(a,b);
       int ans=len1+len2;
       getNext(a,ans);
       while(Next[ans]>len1)
            ans=Next[ans];
       while(Next[ans]>len2)
            ans=Next[ans];
       if(Next[ans]==0)
            printf("0\n");
       else
       {
            for(int i=0;i<Next[ans];i++)
                printf("%c",a[i]);
            printf(" %d\n",Next[ans]);
       }


   }
    return 0;
}

Count the string HDU - 3336

题意:给出 t 组数据,每组给出一个长度为 n 的字符串,对于这个字符串的每个前缀,求其在这个字符串中的匹配次数之和,最后结果 mod 10007

思路:

关键是对 next 数组的理解,next[i] 记录当前位置之前前缀后缀相同的个数,计算出 next 数组之后枚举加和,最后再加上 n 个自身的一个匹配即可

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#define LL long long
const int MOD=10007;
const int N=200000+5;
using namespace std;
 
int Next[N];
char str[N];
int num[N];
void getNext(char p[]){
    Next[0]=-1;
    int len=strlen(p);
    int j=0;
    int k=-1;
 
    while(j<len){
        if(k==-1||p[j]==p[k]) {
            k++;
            j++;
            Next[j]=k;
        }else{
            k=Next[k];
        }
    }
}
 
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        memset(num,0,sizeof(num));
        int n;
        scanf("%d",&n);
        scanf("%s",str);
        getNext(str);
 
        for(int i=1;i<=n;i++)//统计next[i]对应的次数
            num[Next[i]]++;
 
        int res=0;
        for(int i=1;i<=n;i++)
            if(num[i]>0)
                res=(res+num[i])%MOD;
 
        res=(res+n)%MOD;
        printf("%d\n",res);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值