題面
這道題有點坑人啊~
首先,它需要取模,模數是100000000;(窩在這裡死了好久好久,看了別人的**才發現這一點)
然後我發現題解中沒有序列自動機的方法,於是就來一發
首先,雖然序列自動機在定義上與字尾自動機、回文自動機等聽起來比較高大上的演算法同屬於自動機的範疇,但它僅僅是個**普及-**演算法
為何?因為你不學都有可能會(逃)
自動機,就是把乙個字串通過某種關係構成一幅有向無環圖,這樣可以方便我們進行圖上dp
序列自動機的構造方法:
設乙個字符集s,nxt[i][j]表示第i個位置往後第乙個j元素出現的位置;
這個nxt陣列可以o(n)的求出來,可以自行驗證;
for(int i=n-1;i>=0;--i)
她能幹什麼事情呢?(應用)
1.判斷是否是原字串的子串行
當我們構造出nxt陣列之後,可以貪心的尋找子串行;
2.求乙個序列的子串行個數;(可以限定序列的長度)
我們在dag上跑拓撲dp,f[v][j]表示從1~v尋找j個元素的方案數;
顯然的:f[v][j]+=f[u][j-1];
#include #define inc(i,a,b) for(register int i=a;i<=b;i++)
#define dec(i,a,b) for(register int i=a;i>=b;i--)
using namespace std;
char s[3010];
int nxt[3010][40];
int n,m;
long long f[3010][3010];
int rudu[3010];
const int p=998244353;
queueqwq;
void tp()
}}int main()
tp();
long long ans=0;
inc(i,1,n) ans=(ans+f[i][m])%p;
cout<
#### 3.求兩串的公共子串行個數(就是這道題)
#include #define inc(i,a,b) for(register int i=a;i<=b;i++)
#define dec(i,a,b) for(register int i=a;i>=b;i--)
using namespace std;
char a[160],b[160],c[160];
int nxta[160][30],nxtb[160][30],nxtc[160][30];
long long f[160][160][160];
const int mod=100000000;
long long dfs(int x,int y,int z)
}if(x||y||z) ++f[x][y][z];
return f[x][y][z]%mod;
}int main()
dec(i,y-1,0)
dec(i,z-1,0)
cout<
4.求字串的回文子串行個數
首先原串與反串都建一遍;
就相當於從左右端點向中間跑自動機;
顯然:x+y<=n+1才會合法;
但要注意,我們只能統計偶數長度的字串,而不能統計奇數個數的字串;
因為我們永遠都是兩個兩個地串;
long long dfs(int x,int y){
if(f[x][y]) return f[x][y];
for(int i=1;i<=a;++i)
if(nxt1[x][i]&&nxt2[y][i]){
if(nxt1[x][i]+nxt2[y][i]>n+1) continue;
if(nxt1[x][i]+nxt2[y][i]
NOI1808公共子串行
1808 公共子串行 總時間限制 1000ms 記憶體限制 65536kb 描述我們稱序列z z1,z2,zk 是序列x x1,x2,xm 的子串行當且僅當存在 嚴格上公升 的序列 i1,i2,ik 使得對j 1,2,k,有xij zj。比如z a,b,f,c 是x a,b,c,f,b,c 的子串行...
速算遊戲 NOI導刊2011提高(04)
這道題會做到懷疑人生,好了廢話不多說,我們發現這道題是一道深搜。但是字典序卻不知道怎麼排,我們發現沒算乙個運算子就會填加乙個括號,所以我們用乙個char變數貯儲字典序最小的東西。include includetypedef char string 20 int a 4 b 4 ans 4 2 str...
素數密度 NOI導刊2011提高(04)
給定區間 l,r l r 2147483647,r l 1000000 請計算區間中素數的個數。輸入兩個數 l 和 r。輸出一行,區間中素數的個數。樣例輸入 2 11 樣例輸出 5可以發現r l範圍很小,但l和r很大,用普通的篩法時空間都會超。但可以轉換思路,只篩l r的素數。此前先篩出2 r的素數...