Foj 2299 Prefix

题意

给定串s、正整数n,问有多少长度为n的字符串t满足:s[0...i]是t的子串,s[0...i+1]不是。

题解

求有多少长度为n的字符串t满足:s[0...i]是t的子串

这样求出来的数列就是答案的一个前缀和。

具体求法可以对于s[0...i]建一个AC自动机,列出dp式子,状态转移矩阵就很好构造了。

现场主要是没想到每个前缀的方案数要分开求。

代码

#include<cstdio>
#include<cmath>
#include<vector>
#include<iostream>
using namespace std;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define rep(i, a, b) for(int i=(a); i<(b); i++)
#define sz(a) (int)a.size()
#define de(a) cout << #a << " = " << a << endl
#define dd(a) cout << #a << " = " << a << " "
#define all(a) a.begin(), a.end()
#define endl "\n"
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi; const int N = 22, P = 1e9+7; int n, m;
int f[N];
string s; int kpow(int a, int b) {
int res = 1;
while(b) {
if(b&1) res = 1ll*res*a%P;
a = 1ll*a*a%P;
b >>= 1;
}
return res;
} inline int add(int a, int b) {
a+=b;
if(a>=P) a-=P;
return a;
}
inline int sub(int a, int b) {
a-=b;
if(a<0) a+=P;
return a;
}
inline int mul(int a, int b) {
return 1ll*a*b%P;
} struct Mat {
static const int N = ::N;
int a[N][N], n;
Mat(){} Mat(int _n, int v) { n = _n; rep(i, 0, n) rep(j, 0, n) a[i][j] = i==j ? v : 0; }
Mat operator * (const Mat &c) const {
Mat res(n, 0);
rep(i, 0, n) rep(j, 0, n) rep(k, 0, n) res.a[i][j] = add(res.a[i][j], mul(a[i][k], c.a[k][j]));
return res;
}
Mat operator ^ (int b) const {
Mat res(n, 1), a = *this;
while(b) {
if(b&1) res = res*a;
a = a*a;
b>>=1;
}
return res;
}
};
struct Trie {
static const int N = ::N, M = 26;
int ne[N][M], fail[N], fa[N], rt, L, ed[N];
void init() {
fill_n(ne[fail[0] = N-1], M, 0);
fill_n(ed, L, 0);
L = 0;
rt = newnode();
}
int newnode() {
fill_n(ne[L], M, 0);
return L++;
}
void add(string s) {
int p = rt;
rep(i, 0, sz(s)) {
int c = s[i] - 'A';
if(!ne[p][c]) ne[p][c] = newnode(), fa[L-1] = p;
p = ne[p][c];
}
ed[p] = 1;
}
void build() {
vi v;v.pb(rt);
rep(i, 0, sz(v)) {
int c = v[i];
rep(i, 0, M) ne[c][i] ?
v.pb(ne[c][i]), fail[ne[c][i]] = ne[fail[c]][i] :
ne[c][i] = ne[fail[c]][i];
}
}
Mat getMat() {
Mat mat(L, 0);
rep(i, 0, L) rep(j, 0, M) {
int nex = ed[i] ? i : ne[i][j];
++mat.a[i][nex];
}
return mat;
}
}ac; int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
int T;
cin >> T;
while(T--) {
cin >> n >> m >> s;
f[0] = kpow(26, n);
rep(i, 1, m+1) {
ac.init();
ac.add(s.substr(0, i));
ac.build();
Mat res = ac.getMat() ^ n;
f[i] = res.a[0][i];
}
rep(i, 0, m) f[i] = sub(f[i], f[i+1]);
rep(i, 0, m+1) cout << f[i] << endl;
}
return 0;
}

Foj 2299 Prefix(AC自动机、DP)的更多相关文章

  1. POJ1625 Censored!(AC自动机+DP)

    题目问长度m不包含一些不文明单词的字符串有多少个. 依然是水水的AC自动机+DP..做完后发现居然和POJ2778是一道题,回过头来看都水水的... dp[i][j]表示长度i(在自动机转移i步)且后 ...

  2. HDU2296 Ring(AC自动机+DP)

    题目是给几个带有价值的单词.而一个字符串的价值是 各单词在它里面出现次数*单词价值 的和,问长度不超过n的最大价值的字符串是什么? 依然是入门的AC自动机+DP题..不一样的是这题要输出具体方案,加个 ...

  3. HDU2457 DNA repair(AC自动机+DP)

    题目一串DNA最少需要修改几个基因使其不包含一些致病DNA片段. 这道题应该是AC自动机+DP的入门题了,有POJ2778基础不难写出来. dp[i][j]表示原DNA前i位(在AC自动机上转移i步) ...

  4. hdu 4117 GRE Words AC自动机DP

    题目:给出n个串,问最多能够选出多少个串,使得前面串是后面串的子串(按照输入顺序) 分析: 其实这题是这题SPOJ 7758. Growing Strings AC自动机DP的进阶版本,主题思想差不多 ...

  5. hdu 2457(ac自动机+dp)

    题意:容易理解... 分析:这是一道比较简单的ac自动机+dp的题了,直接上代码. 代码实现: #include<stdio.h> #include<string.h> #in ...

  6. HDU 2425 DNA repair (AC自动机+DP)

    DNA repair Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  7. HDU2296——Ring(AC自动机+DP)

    题意:输入N代表字符串长度,输入M代表喜欢的词语的个数,接下来是M个词语,然后是M个词语每个的价值.求字符串的最大价值.每个单词的价值就是单价*出现次数.单词可以重叠.如果不止一个答案,选择字典序最小 ...

  8. tyvj P1519 博彩游戏(AC自动机+DP滚动数组)

    P1519 博彩游戏 背景 Bob最近迷上了一个博彩游戏…… 描述 这个游戏的规则是这样的:每花一块钱可以得到一个随机数R,花上N块钱就可以得到一个随机序列:有M个序列,如果某个序列是产生的随机序列的 ...

  9. bzoj 1030 [JSOI2007]文本生成器(AC自动机+DP)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1030 [题意] 给n个小串,随机构造一个长为m的大串,一个串合法当且仅当包含一个或多个 ...

随机推荐

  1. maven备忘

    maven常见命令 mvn clean mvn compile mvn package mvn clean compile package mvn -Djetty.port= jetty:run mv ...

  2. 《Think Python》第6章学习笔记

    目录 6.1 返回函数值(Return values) 6.2 增量式开发(Incremental development) 6.3 组合(Composition) 6.4 布尔函数(Boolean ...

  3. 使用 IntelliJ IDEA 创建第一个java程序 Hello World

    1.首先打开新建项目窗口 1.1.选择创建java程序 1.2.Project SDK,选择jdk安装路径 1.3.Additional Libraries and Frameworks 额外的库与框 ...

  4. 文件夹操作之判断是否存在(Directory)

    Directory类用于操作文件夹,用于创建.移动和枚举目录和子目录的静态方法.DirectoryInfo类用于典型操作,如复制,移动,重命名,创建和删除目录.他们都可用于获取和设置相关属性或有关创建 ...

  5. Knockout.js Text绑定

    <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8&quo ...

  6. 利用PHP的debug_backtrace函数,实现PHP文件权限管理、动态加载

    简述 可能大家都知道,php中有一个函数叫debug_backtrace,它可以回溯跟踪函数的调用信息,可以说是一个调试利器. 好,来复习一下 01 one(); 02 03 function one ...

  7. WPF中ScrollViewer嵌套引发滚动失灵的Bug

    事情起因 测试报告说存在滚动条不能拖动的情况,我们几个开发人员多次测试都未重现该问题.后面发现是操作系统的问题,在XP和部分Win7上会存在该问题.而在我们开发人员的机器上,包括Win7 SP1,Wi ...

  8. 撩课-Python-每天5道面试题-第7天

    一. 函数的返回值的概念,语法以及注意事项? 场景 当我们通过某个函数, 处理好数据之后, 想要拿到处理的结果 语法 def 函数(): 函数体 return 数据 注意事项 3.1 return 后 ...

  9. Java基础——String

    前言 从去年八月末开始工作一年了,有了大半年的java开发经验,自认为比在大学时期编码能力强了很多,但是基础方面概念模糊的地方感觉越来越多了 (:´д`)ゞ 所以,我准备把这些问题以及工作中遇到的问题 ...

  10. 51Nod 算法马拉松23 开黑记

    惨啊……虽然开了半天黑,但是还是被dalao们踩了…… 第二次开黑,还是被卡在rank20了,我好菜啊……= = 写一写比赛经过吧…… 看到题之后习惯性都打开,A~D看上去似乎并没有什么思路,F应该是 ...