字串的去除敏感字元

2021-07-05 00:25:16 字數 3109 閱讀 6735

l:「****」「****」「you」 「hide」 「york」

s:「shide****me********you」

輸出:s中包含的l乙個單詞,要求這個單詞只出現一次,如果有多個出現一次的,輸出第乙個這樣的單詞

怎麼做?

字串匹配問題。

暴力的話,用字典樹儲存l,剩下來就是暴力破解了

構建字典樹o(n_l), 暴力法的話,最多複雜度為: o(

nl平均

長度∗m

) 最近看ac自動機,其實這道題也是可以用ac自動機解決, **如下:

#include "stdio.h"

#include "string.h"

#define max_word_len 51

struct node

};node* q[max_word_len];

node *root;

int head, tail;

void insert(char *str)

p->isword = true;

}void build_ac() else

q[tail++] = p->next[i];}}

}}void sensitify(char *str, int begin, int size)

}void dealstr(char *str) else

}temp = temp->fail; //this is the longest match, and some times we could not find uck in ****, so we need to check fail pointer recursively }}

}}int main()

build_ac();

scanf("%s", str);

dealstr(str);

printf("%s\n", str);}}

首先介紹一下字典樹,形如下圖:

經常用於字串的查詢。具體**為:

void insert(char *str) 

p->isword = true;

}

其中 字元資訊儲存在 next[charindex], 非空即為當前狀態能接受該字元。或許將字元資訊畫在邊上會更契合點。

接著是ac自動機

ac自動機的原理: 每乙個節點都會有乙個 fail 指標,表示當當前節點無法接受當前字元時,應該跳轉的位置,一般為當前已接受字元的字尾式中能被ac機接受的字串。通俗的來講,當前字串為goa時,字尾式「oa」 「a」中「a」能被ac機接受(狀態2)也就是狀態5的 fail 指標應該是狀態2. 如下圖:

當輸入字串 input 為 goat 時,狀態轉至 5 時,由於當前狀態無法處理字元 t,轉到 fail 指標(狀態2),檢視是否能處理字元 t,正好能處理,進入狀態4。這一過程讀取 input 的指標並沒有回退,也就是整個過程演算法的時間複雜度為o(

ninp

ut_l

en∗t

imea

vera

ge_s

earc

h_ti

me)

具體**:

void dealstr(char *str)  else 

}temp = temp->fail; //this is the longest match, and some times we could not find uck in ****, so we need to check fail pointer recursively }}

}}

上面的 temp = temp->fail 的功能可以嘗試把while 去掉, 嘗試輸入

2 **** uck ****ersayfuuuck****you

檢視輸出結果。

接下來是如何求 fail 指標。這裡面要處理的問題是:

1) 確保失配時,跳轉的 fail 指標應該是最長匹配。

首先演算法的基本框架是bfs。

詳細**是

void build_ac()}}

}

重點在設定 fail 指標:

if (p == root)  else
首先 root 下的所有可接受字元的 fail 指標為自身。

接著其他字元的 fail 指標為遞迴遍歷父指標的 fail 指標中 能夠接受當前字元,如果實在沒有,則指向 root,表示當前的字串不存在能接受的 keyword,重置狀態。

舉個例子:

狀態 3 i=a 的時候,檢視狀態 3 的 fail 指標 root,恰好能接受 i=a, 於是狀態5 的 fail 指標指向狀態 2.

其實 可以把乙個節點的所有一系列(通過遞迴獲取) fail 指標 看作狀態機的同乙個狀態。感興趣可以檢視編譯原理裡面的狀態轉移。

那怎麼確定當前取得的 fail 指標是最長匹配呢 比如 blue ue e , blue e 的 fail 指標應該指向 ue 的 e, 而不是 e 呢? 原因在他的父親節點 u 的 fail 指標指向的是 ue 的 u,所以 blue 的 e fail 指標指向的是 ue 的 e, 同時 ue 的 e 指向的是 e 的 e。 好繞 0.0

後記:

字典樹中使用 next[26] 來儲存字元資訊,有些浪費。如果關鍵字很稀疏的話,大部分的指標空閒,造成浪費。如果只用 node *next,char contant儲存的話,每次查詢的時候都需要遍歷next,如果關鍵字很密集的話,時間開銷過大

鳴謝帶我入門的blog ac自動機演算法

字串去除特定字元

週六,剛顧著陪女朋友玩了,九度oj想ac一道簡單的題目,結果在scanf上遇到了點問題,唉,週六大好的時間就沒有深入研究,今天趁著來公司看了一下scanf實現機制,解決了 靠,蛋疼的csdn,剛才寫了一大堆竟然沒儲存,直接上 了 題目描述 輸入字串s和字元c,要求去掉s中所有的c字元,並輸出結果。輸...

C 去除字串首尾字元或字串

在做乙個屬性入庫的功能,將excel屬性資料匯入到圖層要素當中,這裡excel和sde資料庫資料存在乙個關聯字段,通過關聯字段值進行匹配屬性入庫。在實際業務中,由於普查資料往往某些字段值比較複雜,在寫入到圖層中時使用者可能做一些簡化,例如乙個要素編號為0532bh001,可能錄入到圖層中只錄入bh0...

C 去除字串首尾字元或字串

在做乙個屬性入庫的功能,將excel屬性資料匯入到圖層要素當中,這裡excel和sde資料庫資料存在乙個關聯字段,通過關聯字段值進行匹配屬性入庫。在實際業務中,由於普查資料往往某些字段值比較複雜,在寫入到圖層中時使用者可能做一些簡化,例如乙個要素編號為0532bh001,可能錄入到圖層中只錄入bh0...