題目源自《程式設計師》2023年第8期程式設計擂台
問題描述
最近出現了一種奇異的生物病毒
,這種病毒侵染的範圍很廣
,科學家們經研究發現
,這種病毒的內部存在一種環狀
dnad片斷,
而正常情況下
,生物的基因總是呈線狀排列的
.
因此據
dr.x推測,
病毒侵染某個生物的機率可能正是與此有關
:被侵染生物的
dna中總是或多或少存在著一些片段
,它們與環狀
dn**斷中的一部分是相同的
(可稱之為「匹配
」),而它們中最長的片斷越長
,生物被侵染的可能性就越大
,其後又有研究發現
,某些生物被侵染的機率遠大於其它生物,對此
dr.x推測,
可能是因為環狀
dn**段不僅可以部分地匹配被侵染生物的
dn**斷
,還可以迴圈地匹配
.
例如如果環狀
dn**斷為
abc(
也可以表示為
bca或是
cab,
但它和acb
是不同的
),被侵染生物的
dna為
abbcabcabb,
那麼能被環狀
dn**斷匹配的最長片段就是
bcabcab,
長度為7.
面對大量的實驗資料
,dr.x
希望你能夠幫她設計乙個程式
,計算出被侵染生物的
dna中與環狀
dn**段匹配的最長片段的長度
.
輸入格式
:輸入檔名為
virus.in,
檔案第1
行是乙個正整數
n(n<=1000),
表示環狀
dn**段的長度.第
2行是一長度為
n的字串
(由大小寫英文本母組成,下同
),它描述了環狀
dn**段.第
3行是乙個正整數
m(m<=100000),
表示被侵染生物的
dna的長度,第
4行是一長度為
m的字串
,它描述被侵染生物的
dna.
輸出格式
:輸出檔名為
virus.out,
檔案只需包含乙個數
,即最長片段的長度
.
樣例輸入
virus.in
樣例輸出
virus.out
37
abc
10
abbcabcabb
演算法分析
:
除去背景資訊
,不難看出本題的求解目標是乙個環串
a(即環狀
dn**段
)和乙個線串
b(即被侵染生物的
dna)
的最長公共子串
.
本題可以用動態規劃求解
:我們用
t[i][j]
來表示以線串b的第
i個字元和環串a的第
j個字元結尾的最長公共子串的長度
,顯然有如下公式
:
t[i-1][j-1]+1;a[j]=b[i]且1
t[i][j]=t[i-1][n]+1;a[j]=b[i]
且j=1
0;a[j]!=b[i]
這也是本題的動態轉移方程
例如在樣例中,環串
a是
abc,線串b
是abbcabcabb,則t
如下表所示
(空格表示
0)ji12
3456
78910
11 3
6 2
2 1
4 7
132
5
當然在程式設計實現時
,我們是不會用乙個
100000*1000
的**來動態規劃的,由於
t[i]
只與t[i-1]有關,
所以可以儲存乙個
2*1000
的**,
空間複雜度為
o(n),
時間複雜度為
o(n*m).另外,
逐個拿a[j]
與b[i]
比較也沒有必要
,由於字符集為
,並不太大
,所以參考程式用乙個索引表記錄了每個字元在
a中出現的位置,讀入
b[i]
時直接定位即可
#include
#include
#include
using namespace std;
const int max_n=1000;
int m,n,longest=0;
int firstpos[128];
int nextpos[max_n];
int dptable[2][max_n];
void init() }
void solve()
pos=firstpos[prech];//
為下一次迴圈作初始化
while(pos>=0)
prech=ch;
}cout<
}int main()
上面的程式中用到了一些建立字元索引的小技巧,其中
firstpos
陣列和nextpos
陣列用來記錄某個字元在病毒
dna中出現的位置
,對於乙個字元
ch,首先根據
pos=firstpos[ch]
可以得到該字元在病毒
dna中的第乙個位置
,然後根據
pos=nextpos[pos]
可以得到下乙個位置,當
pos=-1
時說明已經完全遍歷了該字元在病毒
dna中出現的所有位置.在
solve
函式中, for(int i=0;i迴圈用來遍歷被
侵染生物的
dna的每個字元
,dptable
是乙個2*n
的**,
用來儲存動態規劃的資訊
.now
表示當前階段在
dptable
中的行,pre
表示上乙個階段在
dptable
中的行,
迴圈中首先得到被侵染生物的
dna的乙個字元
ch,然後根據
firstpos
和nextpos
依次遍歷該字元在病毒
dna中的每個位置
,並且根據狀態轉移方程計算對於狀態的最優解
,for
迴圈的最後幾行:
pos=firstpos[prech];//
為下一次迴圈作初始化
while(pos>=0)
prech=ch;
prech
始終是上一次迴圈時讀入的字元
ch,這幾行的作用就是將
dptable
的第pre
行全部清
0,這樣下次迴圈時
dptable
的第now
行就已經初始化為0了
.
奇異的 exim 不能收信問題
cpanel的空間,有個網域名稱下面的郵箱,不能收到任何信。通過 tail f var log exim mainlog 發現 2014 04 02 14 03 12 smtp connection from 65.55.116.78 25278 tcp ip connection count 1 ...
紅色病毒問題
醫學界發現的新病毒因其蔓延速度和internet上傳播的 紅色病毒 不相上下,被稱為 紅色病毒 經研究發現,該病毒及其變種的dna的一條單鏈中,胞嘧啶,腺嘧啶均是成對出現的。現在有一長度為n的字串,滿足一下條件 1 字串僅由a,b,c,d四個字母組成 2 a出現偶數次 也可以不出現 3 c出現偶數次...
奇異的恩典
看了部老電影 奇異的恩典 講英國廢奴法案的事,威伯福斯一心推動廢奴法案,因議會貴族在這上面都有利益在,推了多年也沒有進展,英法戰爭開始後,大家的焦點都在戰爭上,其它議案沒人理會,雖大聲疾呼也沒啥見效,支援的團隊都要散夥了。前面這些只是背景,關鍵覺得他們的突破策略很有意思,即然大家都在關心戰爭,因法國...