奇異的病毒問題

2021-04-08 23:44:46 字數 3700 閱讀 1240

題目源自《程式設計師》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出現偶數次...

奇異的恩典

看了部老電影 奇異的恩典 講英國廢奴法案的事,威伯福斯一心推動廢奴法案,因議會貴族在這上面都有利益在,推了多年也沒有進展,英法戰爭開始後,大家的焦點都在戰爭上,其它議案沒人理會,雖大聲疾呼也沒啥見效,支援的團隊都要散夥了。前面這些只是背景,關鍵覺得他們的突破策略很有意思,即然大家都在關心戰爭,因法國...