中文題,不解釋
這道題其實和poj 2778是一樣的,只是需要對矩陣有著更深刻的理解而已。我們很容易便能像poj 2778一樣求出來不包含條件字串的字串方案。只是題目中要求長度小於等於l,所以我們可以在矩陣中手動加乙個點,這個點允許從任何狀態轉移而來。這點的意義表示字串終止。也就是說如果字串轉移到這個點時候小於l,那麼字串最終長度小於l。求出來小於等於l,不包含條件字串的方案數以後,只要求出來總方案數就可以解決問題。
總方案數遞推公式很容易求出來。f[n]=26*f[n-1]+1。(+1表示上一位終止,26表示補充乙個字元)如果遞推去求,超時是必然的。這時候又要用到矩陣的性質,將遞推公式轉化為矩陣。因為遞推公式裡有兩項,所以矩陣就轉化為乙個二維矩陣。[26,1;0,1]^n[f(0),1]。利用矩陣快速冪搞出來,減去不包含條件字串的方案數就可以了。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define up(i,l,h) for(int i=l;i#define down(i,h,l) for(int i=h-1;i>=l;i--)
#define w(a) while(a)
#define mem(a,b) memset(a,b,sizeof(a))
#define inf 0x3f3f3f3f3f3f3f3f
#define ll long long
#define ull unsigned long long
#define maxn 10000
#define eps 1e-10
#define mod 100000
#define n 26
using
namespace
std;
typedef
unsigned ll matrix[35][35];
int ch[35][26];
char st[35];
int sz;
int val[35],f[35];
matrix a,ans,temp;
void insert()
u=ch[u][x];
}val[u]=1;
}void getfail()
}w(!q.empty())
q.push(u);
int v=f[r];
f[u]=ch[v][x];
if(val[f[u]]) }}
}void buildmatrix()
}up(i,0,sz+1)
}void matrixmulti(matrix a,matrix b) }}
memcpy(a,temp,sizeof(temp));
}void quick(int n)
w(n)
matrixmulti(a,a);
n>>=1;
}}int main()
getfail();
buildmatrix();
int k=0;
up(i,0,sz)
}quick(l);
ull ansnum=0;
up(i,0,sz+1)
mem(a,0);
a[0][0]=26;
a[0][1]=a[1][1]=1;
quick(l);
printf("%i64u\n",(ans[0][0]+ans[0][1]-ansnum));
}}
hdu 2243 AC自動機 矩陣加速
給你 n 個病毒,問長度為 1,m 的,包括病毒的有多少。全都是小寫字母。和 poj 2778 有點像。不一樣的是 1 這個是求包括的,我這麼做的,加一維用來表示已經包括了病毒的狀態。2 求長度是 1,m 的。在矩陣裡面維度變成二倍。a 1 1 0 左下面的 1 就是最後所求。a是矩陣的話,就把 1...
MZ hdu 2243 AC自動機 矩陣加速
給你 n 個病毒,問長度為 1,m 的,包括病毒的有多少。全都是小寫字母。和 poj 2778 有點像。不一樣的是 1 這個是求包括的,我這麼做的,加一維用來表示已經包括了病毒的狀態。2 求長度是 1,m 的。在矩陣裡面維度變成二倍。a 1 1 0 左下面的 1 就是最後所求。a是矩陣的話,就把 1...
HDOJ 2243 AC自動機 等比矩陣求和
題目是要說小於l長度的由小寫字母組成的字串有多少個包含所給的串.從正方向想.要求出包含的.並且還要踢去重複包含的.又要加上被多踢的.整個一容斥問題了.但這題明顯是不可行的.那麼換個角度.先求出總共小於l的單詞數 26 1 26 2 26 3 26 l 然後再減去不包括所給字串的單詞.相當於把每個單詞...