bzoj3507 [Cqoi2014]萬用字元匹配
我們將題目輸入的那個含萬用字元的串,記為“萬用字元串”,下面的檔名記為“檔名”,“檔名”數量很少可以依次查詢。
我們先將“萬用字元串”以‘*’為界,將“萬用字元串”分解,得到若干子串,記為“通配子串”
我們將每個“通配子串”各建立一個AC自動機。
而有的“通配子串”可能含‘?’萬用字元,我們將再次按‘?’為界,分解這個“通配子串”,得到的子串記為“劃分子串”,然後將“劃分子串”加入該“通配子串”所在的AC自動機上(原“通配子串”就不加進去了)。
匹配“檔名”時,我們應按“通配子串”的順序依次匹配“檔名”,檢查該“檔名”是否可行,靠前的“通配子串”先匹配,如果某次匹配不成功,該“檔名”不可以匹配。特殊的,對於含‘
還有些細節就是對於兩個萬用字元串"*ab?c"和"ab?c",第二個萬用字元串的a前面不允許有其它字元,我的做法是在萬用字元串的前後加上'{',也就是得到了"{*ab?c{",讀取“檔名”也這做,就可以解決。
另一個細節就是出現萬用字元子串"abc??"時,要求檔名的一段"abc"的後面還有兩個字元,我的做法是:視"??"後面為空串,加入AC自動機(這個也可以特判一下,我的做法可以看下程式碼> <,但是我的程式碼很醜啊)。
最後提一個細節就是:對於萬用字元子串可能有多個相同的劃分子串,比如"abc?abc”。然後你就知道該怎麼做了。
剩下的細節就不必討論了。
#include<bits/stdc++.h> using namespace std; #define idx(c) ((c) - 'a') const int MAX_NODE = 100000 + 10; const int MAX_SIZE = 27; const char ocu = '{'; int ch[MAX_NODE + 10][MAX_SIZE], sz = 1; vector<int> val[MAX_NODE + 10]; //vector型別的結點標記 int f[MAX_NODE + 10], last[MAX_NODE + 10]; int new_node() { return sz++; } int cnt[MAX_NODE + 10]; struct trie { int root, str_cnt; trie() { root = new_node(); str_cnt = 0; } void ins(const string &s, int v) { int i, u = root; for(i = 0; i < s.length(); i++) { int c = idx(s[i]); if(ch[u][c] == 0) ch[u][c] = new_node(); u = ch[u][c]; } val[u].push_back(v); str_cnt++; } void get_fail() { queue<int> q; f[root] = root; last[root] = root; for(int i = 0; i < MAX_SIZE; i++) { int &r = ch[root][i]; if(r == 0) r = root; else { q.push(r); f[r] = last[r] = root; } } while(!q.empty()) { int u = q.front(); q.pop(); for(int i = 0; i < MAX_SIZE; i++) { int &r = ch[u][i]; if(r == 0) { r = ch[f[u]][i]; continue; } q.push(r); f[r] = ch[f[u]][i]; last[r] = val[f[r]].size() ? f[r] : last[f[r]]; } } } bool query(const string &s, int st, int &ed) { memset(cnt, 0, sizeof(cnt)); int u = root; for(int i = st; i < s.length(); i++) { u = ch[u][idx(s[i])]; int tmp = u; for(int j = 0; j < val[root].size(); j++) { int k = i - val[root][j] + 1; if(k >= 0) { cnt[k]++; if(cnt[k] == str_cnt) return ed = i, 1; } } while(tmp != root) { for(int j = 0; j < val[tmp].size(); j++) { int k = i - val[tmp][j] + 1; if(k >= 0) { cnt[k]++; if(cnt[k] == str_cnt) return ed = i, 1; } } tmp = last[tmp]; } } return 0; } }; vector<trie> A; //我將每個AC自動機存在A裡面 bool match(const string &s) { //匹配檔名 int i, next_st = 0, next_ed; for(i = 0; i < A.size(); i++) { //依次匹配AC自動機 bool ok = A[i].query(s, next_st, next_ed); if(ok == 0) break; next_st = next_ed + 1; } return i == A.size(); } trie split(const string &s) { //將劃分子串加入AC自動機 trie res; string tmp; for(int i = 0; ; i++) { if(i < s.length() && s[i] != '?') tmp.push_back(s[i]); else { if(i != 0) res.ins(tmp, i); //實現時我將認為任意一個'?'後都可以補上空串 tmp.clear(); } if(i == s.length()) break; } res.get_fail(); return res; } void prepare(const string &s) { //分離出萬用字元子串然後依次建立AC自動機 string tmp; for(int i = 0; i < s.length(); ) { while(i < s.length() && s[i] != '*') tmp.push_back(s[i++]); A.push_back(split(tmp)); while(i < s.length() && s[i] == '*') i++; tmp.clear(); } } char R[MAX_NODE + 10] = "{"; string buf; int main() { scanf("%s", R + 1); buf = string(R); buf.push_back('{'); prepare(buf); int i, n; scanf("%d", &n); for(i = 1; i <= n; i++) { scanf("%s", R + 1); buf = string(R); buf.push_back('{'); if(match(buf)) puts("YES"); else puts("NO"); } return 0; }
相關推薦
bzoj3507 [Cqoi2014]萬用字元匹配
我們將題目輸入的那個含萬用字元的串,記為“萬用字元串”,下面的檔名記為“檔名”,“檔名”數量很少可以依次查詢。 我們先將“萬用字元串”以‘*’為界,將“萬用字元串”分解,得到若干子串,記為“通配子串” 我們將每個“通配子串”各建立一個AC自動機。 而有的“通配子串”可能含
[Luogu P3167] [BZOJ 3507] [CQOI2014]萬用字元匹配
洛谷傳送門 BZOJ傳送門 題目描述 幾乎所有作業系統的命令列介面(CLI)中都支援檔名的萬用字元匹配以方便使用者。最常見的萬用字元有兩個,一個是星號(*),可以匹配 0
Leetcode 44:萬用字元匹配(超詳細的解法!!!)
給定一個字串 (s) 和一個字元模式 (p) ,實現一個支援 '?' 和 '*' 的萬用字元匹配。 '?' 可以匹配任何單個字元。 '*' 可以匹配任意字串(包括空字串)。 兩個字串完全匹配才算匹配成功。 說明: s 可能為空,且只包含從 a-z 的小寫字母。
D-動態規劃比遞迴快-LeetCode44-萬用字元匹配
題目 給定一個字串 (s) 和一個字元模式 (p) ,實現一個支援 '?' 和 '*' 的萬用字元匹配。 '?' 可以匹配任何單個字元。 '*' 可以匹配任意字串(包括空字串)。 兩個字串完全匹配才算匹配成功。 說明: s 可能為空,且只包含從 a-z 的小寫字母。 p 可能為空,且只包含
萬用字元匹配
給定一個字串 (s) 和一個字元模式 § ,實現一個支援 ‘?’ 和 ‘*’ 的萬用字元匹配。 ‘?’ 可以匹配任何單個字元。 ‘*’ 可以匹配任意字串(包括空字串)。 兩個字串完全匹配才算匹配成功。 說明: s 可能為空,且只包含從 a-z 的小寫字母。 p 可能為空,且只包含
leetcode 44. 萬用字元匹配
給定一個字串 (s) 和一個字元模式 (p) ,實現一個支援 '?' 和 '*' 的萬用字元匹配。 '?' 可以匹配任何單個字元。 '*' 可以匹配任意字串(包括空字串)。 兩個字串完全匹配才算匹
【leetCode】44_萬用字元匹配
dp: class Solution { public: bool isMatch(string s, string p) { //tag 用於dp,tag[i][j]代表s的子串s[0,i-1] 可以匹配 p的子串p[0,j-1]。
【LeetCode】44. 萬用字元匹配
題目描述 思路(與10. 正則表示式匹配類似) dp[ i ][ j ] 表示 s 的前 i 個字元與 p 的前 j 個字元的匹配結果。 先寫邊界情況,再寫 dp 方程,若 p[ j - 1] 為 * ,dp[ i ][ j ] = dp[ i - 1][ j
leetcode 44 ---- 動態規劃(困難) :萬用字元匹配(java)
1. 問題:給定一個字串 (s) 和一個字元模式 (p) ,實現一個支援 '?' 和 '*' 的萬用字元匹配。 '?' 可以匹配任何單個字元。 '*' 可以匹配任意字串(包括空字串)。 兩個字串完全匹配才算匹配成功。 說明: s 可能為空,且只包含從 a-z 的小
萬用字元匹配_講解和python3實現
題目描述 給定一個字串 (s) 和一個字元模式 § ,實現一個支援 ‘?’ 和 ‘*’ 的萬用字元匹配。 ‘?’ 可以匹配任何單個字元。 ‘*’ 可以匹配任意字串(包括空字串)。 兩個字串完全匹配才算匹配成功。 說明: s 可能為空,且只包含從 a-z 的小寫字母。 p 可能
LeetCode 10 & 44 正則表示式匹配 & 萬用字元匹配 字串匹配問題
10 正則表示式匹配 給定一個字串 (s) 和一個字元模式 (p)。實現支援 ‘.’ 和 ‘*’ 的正則表示式匹配。 ‘.’ 匹配任意單個字元。 ‘*’ 匹配零個或多個前面的元素。 匹配應該覆蓋整個字串 (s) ,而不是部分字串。 說明: s 可能為
44. 萬用字元匹配
給定一個字串 (s) 和一個字元模式 (p) ,實現一個支援 '?' 和 '*' 的萬用字元匹配。 '?' 可以匹配任何單個字元。 '*' 可以匹配任意字串(包括空字串)。 兩個字串完全匹配才算匹配成功。 說明: s 可能為空,且只包含從 a-z 的小寫字母。 p
LintCode (192)萬用字元匹配
題目 判斷兩個可能包含萬用字元“?”和“*”的字串是否匹配。匹配規則如下: '?' 可以匹配任何單個字元。 '*' 可以匹配任意字串(包括空字串)。 兩個串完全匹配才算匹配成功。 函式介面如下: bool isMatch(const char *s, const
String、動態規劃——wildcard-matching 萬用字元匹配
Implement wildcard pattern matching with support for'?'and'*'. '?' Matches any single character. '*' Matches any sequence of characters
LeetCode-44.萬用字元匹配(考察點:動態規劃)
給定一個字串 (s) 和一個字元模式 (p) ,實現一個支援 '?' 和 '*' 的萬用字元匹配。 '?' 可以匹配任何單個字元。 '*' 可以匹配任意字串(包括空字串)。 兩個字串完全匹配才算匹配成功。 說明: s 可能為空,且只包含從 a-z 的小寫字母。 p
【每日面試題】字串萬用字元匹配問題
題目:在一篇英文文章中查詢指定的人名,人名使用二十六個英文字母(可以是大寫或小寫)、空格以及兩個萬用字元組成(*、?),萬用字元“*”表示零個或多個任意字母,萬用字元“?”表示一個任意字母。 如:“J* Smi??” 可以匹配“John Smith” . 請用C語言實現如下
Java 萬用字元匹配查詢檔案
============================= 字串匹配例子 String s = "*txt.*"; s = s.replace('.', '#'); s = s.replaceAll("#", "////."); s =
萬用字元匹配-LintCode
判斷兩個可能包含萬用字元“?”和“*”的字串是否匹配。匹配規則如下: '?' 可以匹配任何單個字元。 '*' 可以匹配任意字串(包括空字串)。 兩個串完全匹配才算匹配成功。 函式介面如下: b
華為code中的字串萬用字元匹配
#define FALSE 0 #define TRUE 1 #define M 300 #include<stdio.h> #include<string.h> int equal(char *s, char *p) { char tem
python leetcode 044 萬用字元匹配(困難)解題報告
給定一個字串 (s) 和一個字元模式 (p) ,實現一個支援 '?' 和 '*' 的萬用字元匹配。'?' 可以匹配任何單個字元。 '*' 可以匹配任意字串(包括空字串)。 兩個字串完全匹配才算匹配成功。說明:s 可能為空,且只包含從 a-z 的小寫字母。p 可能為空,且只包含