字串行的子串行是指從給定字串行中隨意地(不一定連續)去掉若干個字元(可能乙個也不去掉)後所形成的字串行。令給定的字串行x=「x0,x1,…,xm-1」,序列y=「y0,y1,…,yk-1」是x的子串行,存在x的乙個嚴格遞增下標序列,使得對所有的j=0,1,…,k-1,有xij = yj。例如,x=「abcbdab」,y=「bcdb」是x的乙個子串行。對給定的兩個字串行,求出他們最長的公共子串行長度,以及最長公共子串行個數。
第1行為第1個字串行,都是大寫字母組成,以」.」結束。長度小於5000。
第2行為第2個字串行,都是大寫字母組成,以」.」結束,長度小於5000。
第1行輸出上述兩個最長公共子串行的長度。
第2行輸出所有可能出現的最長公共子串行個數,答案可能很大,只要將答案對100,000,000求餘即可。
abcbdab.
bacbbd.47
反思:題目雖然看題解看懂了,自己也敲出來了,但是當別人問的時候不能清晰的講出自己思路(甚至還講錯了,這個是真tm尷尬),這樣是失敗的,雖然ac了,然並卵;
這題第2問嚴格的來說並不能算動態規劃(不滿足無後效性),只是借用其中狀態如何轉移;
題解:第一問模板題,第二問不會寫
有2個問題:第lcs的個數,**會爆空間(需要滾動陣列)
f[i][j]表示a前i位,b前j位的最長公共子串行長度,用g[i][j]表示a前i位,b前j位的最長公共子串行數目
g[i][j]如何轉移呢?考慮這是從那一步推過來的,
比如當 f[i][j]=f[i−1][j],就可以認為從f[i-1][j]轉移過來,
那麼g[i][j]=g[i-1][j];
那麼有如下關係式:
當f[i][j]=f[i−1][j],g[i][j]+=g[i−1][j]
當f[i][j]=f[i][j−1],g[i][j]+=g[i][j−1]
當a[i]=b[j]且f[i][j]=f[i−1][j−1]+1,g[i][j]+=g[i−1][j−1],看起來好像沒啥問題,but...樣例都沒法過,orz
其實是忽略了一種情況(本質上是對這個狀態轉移不是特別清晰),
當a[i]≠b[j],並且f[i
][j]
=f[i
−1][
j−1]
'>f[i][j]=f[i−1][j−1]
f[i][j]=f[i−1][j−1],(就是a,b的最後一位均沒有匹配,會導致上面的2個if條件都會滿足,f[
i][j
]=f[
i−1]
[j−1
]'>g[i][j]同時累計上g[i-1][j]和g[i][j-1]時,明顯有重複的情況f[
i][j
]=f[
i−1]
[j−1
]'>。f[
i][j
]=f[
i−1]
[j−1
]'>
1 #include 2 #include 3 #include 4using
namespace
std;56
const
int mod=100000000;7
const
int maxn=5005;8
char
a[maxn], b[maxn];
9int f[2][maxn],g[2
][maxn];
1011
intmain()
1234
else
3540
if(f[now][j]==f[pre][j])
41 g[now][j]=(g[now][j]+g[pre][j])%mod;
4243
if(f[now][j]==f[now][j-1
])44 g[now][j]=(g[now][j]+g[now][j-1])%mod;45}
46}47 printf("
%d\n%d
",f[n&1][m],g[n&1
][m]);
48return0;
49 }
bzoj 2423 最長公共子串行
題意 中文題意,略。思路 第一問,求最長公子序列,模板題。第二問,求最長公共子串行的個數,這個就比較有意思了。設len i j 表示表示第乙個串到i位置,第二個串到j位置時的長度。設lcs i j 表示第乙個串到i位置,第二個串到j位置時,lcs的個數。當a i b j 那麼最長公共子串行肯定是可以...
BZOJ2423 最長公共子串行(動態規劃)
bzoj 洛谷今天考試的時候,神仙出題人 fdf 把這道題目作為乙個二合一出了出來,我除了orz還是只會orz。對於如何 o n 2 求解最長的長度是很簡單的。設 f i j 表示第乙個串匹配到了 i 第二個串匹配到了 j 的最大長度。那麼轉移很顯然,要麼 i 向後挪動一位,要麼 j 向後挪動一位,...
求N階乘的長度
給乙個數x,len log10 x 1就是x這個數的長度 當n的值不超過10 6時 那麼n的階乘長度 log10 1 2 3 4 n 1 log10 1 log10 2 log10 3 log10 4 log10 n 1 include includeint main 當n比較大時,再用上面這種方法...