博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[HDU 3336]Count the String[kmp][DP]
阅读量:5307 次
发布时间:2019-06-14

本文共 1580 字,大约阅读时间需要 5 分钟。

题意:

求一个字符串的所有前缀串的匹配次数之和.

思路:

首先仔细思考: 前缀串匹配.

n个位置, 以每一个位置为结尾, 就可以得到对应的一个前缀串.

对于一个前缀串, 我们需要计算它的匹配次数.

k = next [ j ]

表示前缀串 Sj 的范围内(可以视为较小规模的子问题), 前缀串 Sk 是最长的&能够匹配两次的前缀串.

这和我们需要的答案有什么关系呢?

题目是求所有前缀串的匹配次数之和, 那么可以先求前缀串 Si 在整个串中的匹配次数, 再加和.

到此, 用到了两个"分治", 一是将大规模的问题减小为小规模的问题, 二是将询问的最终结果拆分成一个个步骤, 则专注于分析核心步骤.

可设dp[ i ]为前缀串 Si 在总串中出现的次数.

dp[i] = 1;

dp[next[i]] += dp[i];

 

#include 
#include
const int MAXN = 200005;const int MOD = 10007;int dp[MAXN],next[MAXN];char s[MAXN];//46MS 1960Kvoid prekmp(){ next[0] = -1; int j = -1; for(int i=1;s[i];i++) { while(j!=-1 && s[j+1]!=s[i]) j = next[j]; if(s[j+1]==s[i]) j++; next[i] = j; }}int main(){ int T; scanf("%d",&T); while(T--) { int n; scanf("%d",&n); scanf("%s",s); prekmp(); for(int i=0;i

还有另一种思路:

 

可以将前缀的匹配次数视为包含的前缀个数.

最终的问题是求s中 (设每一种前缀i包含的前缀个数Fi ) ΣFi .

dp[i]为前缀串s[0...i]包含的前缀个数的新增数目(相对于前缀串s[0...i-1]).

dp[i] = dp[next[i]] + 1;//1表示它本身也是新增的一个前缀

 

#include 
#include
const int MAXN = 200005;const int MOD = 10007;int dp[MAXN],next[MAXN];char s[MAXN];//62MS 1960Kvoid prekmp(){ next[0] = -1; int j = -1; for(int i=1;s[i];i++) { while(j!=-1 && s[j+1]!=s[i]) j = next[j]; if(s[j+1]==s[i]) j++; next[i] = j; }}int main(){ int T; scanf("%d",&T); while(T--) { int n; scanf("%d",&n); scanf("%s",s); prekmp(); memset(dp,0,sizeof(int)*(n+1)); for(int i=0;i

 

 

转载于:https://www.cnblogs.com/james1207/p/3320087.html

你可能感兴趣的文章
脚本删除文件下的文件
查看>>
实用拜占庭容错算法PBFT
查看>>
java的二叉树树一层层输出,Java构造二叉树、树形结构先序遍历、中序遍历、后序遍历...
查看>>
php仿阿里巴巴,php实现的仿阿里巴巴实现同类产品翻页
查看>>
Node 中异常收集与监控
查看>>
七丶Python字典
查看>>
Excel-基本操作
查看>>
面对问题,如何去分析?(分析套路)
查看>>
Excel-逻辑函数
查看>>
面对问题,如何去分析?(日报问题)
查看>>
数据分析-业务知识
查看>>
nodejs vs python
查看>>
poj-1410 Intersection
查看>>
Java多线程基础(一)
查看>>
TCP粘包拆包问题
查看>>
Java中Runnable和Thread的区别
查看>>
SQL Server中利用正则表达式替换字符串
查看>>
POJ 1015 Jury Compromise(双塔dp)
查看>>
论三星输入法的好坏
查看>>
Linux 终端连接工具 XShell v6.0.01 企业便携版
查看>>