串的主分支-字符串 程序員
字符串主要用於編程,概念說明、函數解釋、用法詳述見正文,正則表達式
這裏補充一點:字符串在存儲上相似字符數組,因此它每一位的單個元素都是能夠提取的,算法
如s=「abcdefghij」,則s[1]=「b」,s[9]="j",而字符串的零位正是它的長度,如s[0]=10,編程
這能夠給咱們提供不少方便,如高精度運算時每一位均可以轉化爲數字存入數組。數組
中文名 字符串 安全
外文名 Character string
拼 音 zi fu chuan
簡 稱 串(String)
記 做 s=「a1a2···an」(n>=0)
釋 義 編程語言中表示文本的數據類型閉包
簡介編程語言
字符串或串(String)是由數字、字母、下劃線組成的一串字符。通常記爲 s=「a1a2···an」(n>=0)。它是編程語言中表示文本的數據類型。在程序設計中,字符串(string)爲符號或數值的一個連續序列,如符號串(一串字符)或二進制數字串(一串二進制數字)。
一般以串的總體做爲操做對象,如:在串中查找某個子串、求取一個子串、在串的某個位置上插入一個子串以及刪除一個子串等。兩個字符串相等的充要條件是:長度相等,而且各個對應位置上的字符都相等。設p、q是兩個串,求q在p中首次出現的位置的運算叫作模式匹配。串的兩種最基本的存儲方式是順序存儲方式和連接存儲方式。函數
設 Σ 是叫作字母表的非空有限集合。Σ 的元素叫作「符號」或「字符」。在 Σ 上的字符串(或字)是來自 Σ 的任何有限序列。例如,若是 Σ = {0, 1},則 0101 是在 Σ 之上的字符串。
字符串的長度是在字符串中字符的數目(序列的長度),它能夠是任何非負整數。「空串」是在 Σ 上的惟一的長度爲 0 的字符串,並被指示爲 ε 或 λ。
在 Σ 上的全部長度爲 n 的字符串的集合指示爲 Σn。例如,若是 Σ = {0, 1} 則 Σ2 = {00, 01, 10, 11}。注意 Σ0 = {ε} 對於任何字母表 Σ。
在 Σ 上的全部任何長度的字符串的集合是 Σ 的Kleene閉包並被指示爲 Σ*。 依據Σn, 。例如,若是 Σ = {0, 1} 則 Σ* = {ε, 0, 1, 00, 01, 10, 11, 000, 001, 010, 011, …}。儘管 Σ* 自身是可數無限的,Σ* 的全部元素都有有限長度。
在 Σ 上一個字符串的集合(就是 Σ* 的任何子集)被稱爲在 Σ 上的形式語言。例如,若是 Σ = {0, 1},則帶有偶數個零的字符串的集合({ε, 1, 00, 11, 001, 010, 100, 111, 0000, 0011, 0101, 0110, 1001, 1010, 1100, 1111, …})是在 Σ 上的形式語言。ui
字符編碼
歷史上,字符串數據類型爲每一個字符分配一個字節,儘管精確的字符集隨着區域而改變,字符編碼足夠相似得程序員能夠忽略它
— 同一個系統在不一樣的區域中使用的字符集組要麼讓一個字符在一樣位置,要麼根本就沒有它。這些字符集典型的基於ASCII碼
或EBCDIC碼。
意音文本的語言好比漢語、日語和朝鮮語(合稱爲CJK)的合理表示須要多於256個字符(每字符一個字節編碼的極限)。常規的解決
涉及保持對ASCII碼的單字節表示並使用雙字節來表示CJK字形。現存代碼在用到它們會致使一些字符串匹配和切斷上的問題,嚴
重程度依賴於字符編碼是如何設計的。某些編碼好比EUC家族保證在ASCII碼範圍內的字節值只表示ASCII字符,使得使用這些字
符做爲字段分隔符的系統獲得編碼安全。其餘編碼如ISO-2022和Shift-JIS不作這種擔保,使得基於字節的代碼作的匹配不安全。
另外一個問題是若是一個字符串的開頭被刪除了,對解碼器的重要指示或關於在多字節序列中的位置的信息可能就丟失了。另外一個
問題是若是字符串被鏈接到一塊兒(特別是在被不知道這個編碼的代碼截斷了它們的結尾以後),第一個字符串可能不能致使編碼器
進入適合處理第二個字符串的狀態中。
Unicode也有些複雜的問題。多數語言有Unicode字符串數據類型(一般是UTF-16,由於它在Unicode補充位面介入以前就被增
加了)。在Unicode和本地編碼之間轉換要求理解本地編碼,這對於現存系統要一塊兒傳輸各類編碼的字符串而又沒有實際標記出它
們用了什麼編碼就是個問題。
主要操做
1. 鏈接運算 concat(s1,s2,s3…sn) 至關於s1+s2+s3+…+sn.
例:concat(‘11’,'aa’)='11aa’;
2. 求子串 Copy(s,I,I) 從字符串s中截取第I個字符開始後的長度爲l的子串。
例:copy(‘abdag’,2,3)=’bda’
3. 刪除子串 過程 Delete(s,I,l) 從字符串s中刪除第I個字符開始後的長度爲l的子串。
例:s:=’abcde’;delete(s,2,3);結果s:=’ae’
4. 插入子串 過程Insert(s1,s2,I) 把s1插入到s2的第I個位置
例:s:=abc;insert(‘12’,s,2);結果s:=’a12bc’
5. 求字符串長度 length(s) 例:length(‘12abc’)=5
在ASP中 求字符串長度用 len(s)例: len("abc12")=5
6. 搜索子串的位置 pos(s1,s2) 若是s1是s2的子串 ,則返回s1的第一個字符在s2中的位置,若不是子串,則返回0.
例:pos(‘ab’,’12abcd’)=3
7. 字符的大寫轉換。 Upcase(ch) 求字符ch的大寫體。
例:upcase(‘a’)=’A’
8. 數值轉換爲數串 過程 Str(x,s) 把數值x化爲數串s.
例:str(12345,s); 結果s=’12345’
9. 數串轉換爲數值 過程val(s,x,I) 把數串s轉化爲數值x,若是成功則I=0,不成功則I爲無效字符的序數,第三個參數也可不傳
例:val(‘1234’,x,I);結果 x:=1234
主要算法
字符串查找算法
正則表達式算法
模式匹配
字符串的模式匹配算法(KMP)
AC自動機
後綴數組/樹/自動機
(這是一些字符串處理算法,在字符串上進行不一樣的處理)
KMP(字符串的模式匹配算法)
KMP算法的名字是由這個算法的三個創始人Knuth、Morris、Pratt名字的首字母縮寫而得名的
下面是KMP算法的C語言實現
#include <stdio.h> #include <string.h> #include <stdlib.h> typedef int Position; #define NotFound -1 void BuildMatch( char *pattern, int *match ) { Position i, j; int m = strlen(pattern); match[0] = -1; for ( j=1; j<m; j++ ) { i = match[j-1]; while ( (i>=0) && (pattern[i+1]!=pattern[j]) ) i = match[i]; if ( pattern[i+1]==pattern[j] ) match[j] = i+1; //i回退的總次數不會超過i增長的總次數 else match[j] = -1; } } Position KMP( char *string, char *pattern ) { int n = strlen(string); //O(n) int m = strlen(pattern); //O(m) Position s, p, *match; if ( n < m ) return NotFound; match = (Position *)malloc(sizeof(Position) * m); BuildMatch(pattern, match); //Tm=O(m) s = p = 0; while ( s<n && p<m ) { //O(n) if ( string[s]==pattern[p] ) { s++; p++; } else if (p>0) p = match[p-1]+1; else s++; } return ( p==m )? (s-m) : NotFound; } int main() { char string[] = "This is a simple example."; char pattern[] = "simple"; Position p = KMP(string, pattern); if (p==NotFound) printf("Not Found.\n"); else printf("%s\n", string+p); return 0; }
KMP這個算法的關鍵在於下面這個BuildMatch函數的實現
這裏有個值得注意的地方
PS:當pattern[match[j-1]+1]!=pattern[j]時,
下一個待與pattern[j]比較的元素下標爲:
match[match[j-1]]+1
過程的變化
經過對上面的分析咱們能夠獲得KMP算法的時間複雜度爲 T=O(n+m)
(這對於形如查找指定文本中的關鍵字之類的問題而言效率已經很高了哦)
2019-12-22 12:54:08