hdu3336 KMP + DP 前缀数组出现的次数

来源:互联网 发布:天天炫舞开挂软件下载 编辑:程序博客网 时间:2024/06/03 21:37
题意:
      给你一个串,问你他的所有前缀子串在本串中的出现次数,注释:abc的前缀子串是
a ab abc;


思路:
     还是利用了next数组,先对子串求出next数组,再开一个数组dp,初始化全是1,因为每个以当前i结尾的都至少是1,然后从后往前更新,把以i结尾的加到以next[i]结尾的上,
运用的next数组的特点相当于 123123123 最后一个3加到倒数第二个3,倒数第二个3再加到第一个3 那么以3结尾的(123)出现了三次,以3结尾的(123123)出现了两次,以3结尾的(123123123) 出现了一次。
例子详细数据: 


原串   123123123
next   000123456
  dp   333222111


提示:

    这个题目的串之间是可以交叉的,但不可以完全重叠,比如对与这个题目11111的答案是15.


#include<stdio.h>#include<string.h>#define N 200000 + 100char str[N];int next[N];int dp[N];void get_next(int m){   int j ,k;   j = 0 ,k = -1;   next[0] = -1;   while(j < m)   {      if(k == -1 || str[j] == str[k])      next[++j] = ++k;      else k = next[k];   }   return ;}int main (){   int t ,m ,i;   scanf("%d" ,&t);   while(t--)   {      scanf("%d" ,&m);      scanf("%s" ,str);      get_next(m);      for(i = 1 ;i <= m ;i ++)      dp[i] = 1;      int sum = 0;      for(i = m ;i >= 1 ;i --)      {         if(next[i])         {            dp[next[i]] += dp[i];            dp[next[i]] %= 10007;         }         sum += dp[i];         sum %= 10007;      }      /*      for(i = 1 ;i <= m ;i ++)      printf("%d " ,next[i]);      printf("\n");      for(i = 1 ;i <= m ;i ++)      printf("%d " ,dp[i]);      printf("\n");      */      printf("%d\n" ,sum);   }   return 0;}

0 0
原创粉丝点击