oj:
簡單翻譯:
給你乙個n*m的字元矩陣t,在給你乙個x*y的字元矩陣p,問p在t中能完全匹配幾個位置。
這個題我們利用ac自動機解決首先要解決兩個問題:
1.要想p與t的的某個位置完全匹配,那麼p的每一行要與t的對應的部分匹配,所以可以把p每一行看成模式串構造出ac自動機。
然後在t中每一行逐一匹配,找到p中的所有模式串,與t中的每乙個匹配點。我們要記錄一些東西,記錄匹配到的串是從t當前行的哪個一列開始匹配,還有匹配到的模式串是哪乙個。我們用count[r][c]表示t中以(r,c)為左上角,與p等大矩形中有多少個完整的行與p對應的位置行完全相同。那麼如果p的第i行出現在t第r行出現匹配,匹配開始的列為c,意味著count[r-i][c]應該加1。最終count[r][c]=p的行數的那些位置,就是乙個匹配點。
2.如果給定的模式串中存在重複的串,如果不對ac自動化機進行改造我們就不能得到想要的結果,因為我們在匹配的時候要記錄當前匹配到的是哪乙個模式串,但是有兩個相同的,怎麼辦,我們該記錄哪乙個?因為匹配到的p中的哪一行不能確定。既然這樣,我們匹配到某個存在重複的模式串之後,我們可以將這個重複的模式串在p中所有可能的行,對應的count位置都進行加1操作,就解決了這個問題。因為他們匹配結果屬於不同的小矩陣,所以對最終的結果沒有影響
**實現:
#include #include #include #define max 10001
#define array_sizeof(t) ((size_t)(&t+1) - (size_t)(&t))
char map[1001][1001];
char p[101][101];
// 記錄小矩陣中匹配了多少對應的行
int match[1001][1001];
typedef structqueue;
typedef structtrie;
trie trie;
int idx(char c);
void push(int data);
int pop();
int isempty();
void buildac();
void insert(char *s,int index);
int queue[max],next,pre,size;
void buildac()
}while(!isempty())
trie.fail[index] = trie.word[pfail][i];
trie.last[index] = trie.val[trie.fail[index]] ? trie.fail[index] :
trie.last[trie.fail[index]];}}
}}void insert(char *s,int index)
}}void init()
}int main()
scanf("%d%d",&x,&y);
for(i=0;ibuildac();
for(i=0;iint node = nextnode;
while(trie.last[node])
curnode = nextnode;
}else}}
}int sum = x;
int res = 0;
for(i=0;i}
}printf("%d\n",res);
}return 0;
}
Uva11468 AC自動機 概率dp
這題把ac自動機和dp結合了下,題意就是給你一些模式串,給你選擇每個字元的概率,讓你選擇l個字元,求不出現模式串的概率。先把模式串都插入ac自動機,用乙個match陣列記錄該節點是否是單詞節點,特別注意下這裡單詞節點可能是從0節點開始,也肯能由字尾構成單詞節點,所以得加一句match i match...
模式串匹配 KMP演算法和AC自動機(二)
部落格 模式串匹配 kmp演算法和ac自動機 二 中講了kmp原理和實現,kmp演算法針對的是單模式串的匹配問題,而ac自動機是能夠解決多模式穿匹配問題的演算法,曾嘗試自己實現乙個ac自動機,但是發現還是挺有難度的,於是在網上看了一些大神的模板,在這裡 學習一下 下面的部落格 kmp 大多 是用來解...
洛谷 5357 模板 AC自動機(二次加強版)
題目描述 給你乙個文字串 s 和 n 個模式串 t 1.n t t1 n 請你分別求出每個模式串 t it i ti 在 s 現的次數。輸入格式 第一行包含乙個正整數 n 表示模式串的個數。接下來 n 行,第 i 行包含乙個由小寫英文本母構成的字串 t it i ti 最後一行包含乙個由小寫英文本母...