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. cmd sc命令进行服务操作

    sc 命令可以注册.删除和查询系统服务 sc可供选择的参数有很多,这里不详细描述.只介绍简单的最基本的sc使用方式. 1. sc create 创建windows服务 eg: sc \\myserve ...

  2. PgAdmin4连接数据库报错:Unable to connect to server: ERROR: unrecognized configuration parameter "bytea_output"

    原因: PgAdmin 4不再支持PostgreSQL 9.0 和更早的版本 我的版本是8.2.15 template1=# select version(); version ----------- ...

  3. java并发编程(9)内存模型

    JAVA内存模型 在多线程这一系列中,不去探究内存模型的底层 一.什么是内存模型,为什么需要它 在现代多核处理器中,每个处理器都有自己的缓存,定期的与主内存进行协调: 想要确保每个处理器在任意时刻知道 ...

  4. IOS7 导航栏适配二

    ios7下的app都是全屏的,意思就是所有控制器的view默认都是从  屏幕的 (0,0)开始. 这时候用到导航栏时,往往会出现被导航栏挡住情况. 最明显的是用到tableView时,第一行的数据会被 ...

  5. 百度搜索URL参数含义

    序号 参数 含义 1 tn 搜索框所属网站.比如 tn=sitehao123,就是 http://www.hao123.com/ 左上那个搜索框(指通过什么方式到达百度首页搜索界面;) 2 s?wd ...

  6. [C语言] 数据结构概述

    1.数据结构概述 定义 我们如何把现实中大量而复杂的问题以特定的数据类型和特定的存储结构保存到主存储器(内存)中, 以及在此基础上为实现某个功能(比如查找.删除.查找.某个元素,对所有元素进行排序)而 ...

  7. [javaSE] GUI(Action事件)

    对自己定义的类规范化一下,事件和图形化组件分离出来 定义一个类FrameDemo 定义成员属性Frame frame 定义成员属性Botton 定义构造方法FrameDemo() 定义初始化方法ini ...

  8. mysql数据库重点(基础优化)

    ### Mysql性能优化 尽量不要写select * ,如果需要全表数据,使用select 加所有字段列名称查询代替* 尽量减少字段列的数学计算,如:where num * 2 >= 30,可 ...

  9. 设计模式入门,适配器模式,c++代码实现

    // test07.cpp : Defines the entry point for the console application.// #include "stdafx.h" ...

  10. Java Future源码分析

    JDK future框架,提供了一种异步编程模式,基于线程池的.将任务runnable/callable提交到线程池executor,返回一个Future对象.通过future.get()获取执行结果 ...