【考研必備】c++串的基礎(chǔ)操作和kmp算法實(shí)現(xiàn)

其實(shí)串這塊還是很簡單的幌缝,主要是kmp算法讓人頭大脆粥。考研書上基本都是c語言struct寫的,個人感覺還是用類寫比較清楚一些膏秫。

復(fù)習(xí)的思維導(dǎo)圖

串的結(jié)構(gòu)定義

定長順序存儲表示

給串尾加上'\0'作為串結(jié)束的標(biāo)記。同時也設(shè)定length。這樣做雖然多用一個單位的存儲空間匣缘,但就是代碼中用起來最方便的形式澄成。

const int maxSize=99;
class Str{
    public:
        char str[maxSize+1];
        int length;
};

串的動態(tài)分配存儲表示和重新賦值

#include <iostream>
using namespace std;
const int maxSize=99;
class Str{
    public:
        char *ch; 
        int length=0;
        Str(char *c){
            ch=c;
            while(*c){
                ++length;
                ++c;
            }
        }
    int reassign(char* c){
        if(ch){
            ch=NULL;
            length=0;
            int len=0;
            char *temp;
            temp=c;
            while(*temp){
                ++len;
                ++temp;
            }
            if(len==0){ // 新字符串為空串 
                ch=NULL;
            }else{
                ch=c;
                length=len;
            }
            return 1;
        }
        return 0;
    }
};
int main(){
    Str s("input");
    s.reassign("hello world!!");
    cout<<s.length; // 13 
    return 0;
}

串比較

有兩個串a(chǎn),b,如果a的ASCII碼小于b的ASCII碼,則返回a小于b標(biāo)記亭敢,如果a的ASCII碼大于b的ASCII碼滚婉,返回a大于b的標(biāo)記,如果a等于b的ASCII碼帅刀,則按照之前的規(guī)則繼續(xù)比較兩串中的下一對字符让腹。經(jīng)過上述步驟,在沒有比較出a和b大小的情況下扣溺,先結(jié)束的串為較小串骇窍。兩串同時結(jié)束,只要返回兩串相等標(biāo)記锥余。

int strCompare(Str s1,Str s2){
    int i=0;
    while(i<s1.length&&i<s2.length){
        if(s1.ch[i]!=s2.ch[i]){
            return s1.ch[i]-s2.ch[i];
        }
        i++;
    }
    return s1.length-s2.length;
}
int main(){
    Str s("input1");
    Str s1("input1");
    int res=strCompare(s,s1);
    cout<<res; // 0
}

串連接

如果a的ASCII碼小于b的ASCII碼腹纳,則返回a小于b標(biāo)記,如果a的ASCII碼大于b的ASCII碼驱犹,返回a大于b的標(biāo)記嘲恍,如果a等于b的ASCII碼,則按照之前的規(guī)則繼續(xù)比較兩串中的下一對字符雄驹。經(jīng)過上述步驟佃牛,在沒有比較出a和b大小的情況下,先結(jié)束的串為較小串医舆。兩串同時結(jié)束吁脱,只要返回兩串相等標(biāo)記。

int concat(Str &target,Str s1,Str s2){
    if(target.ch){
        target.ch=NULL;
    }
    target.ch=new char;
    int i=0;
    while(i<s1.length){
        target.ch[i]=s1.ch[i];
        i++;
    }
    
    int j=0;
    while(j<s2.length){
        target.ch[i+j]=s2.ch[j];
        j++;
    }
    target.length=s1.length+s2.length;
    
    return 1;
}
int main(){
    Str s1("hello");
    Str s2(" world");
    Str target("");
    concat(target,s1,s2);
    cout<<target.length<<endl; // 11
}

求子串

從給定串中某一位置開始到某一位置結(jié)束的串的操作稱為求子串操作彬向。

int Str::substring(Str &str,int pos,int len){
    if(str.ch){
        str.ch=NULL;
    }
    if(pos+len>length){
        cout<<"所求位置的字符串長度溢出"<<endl;
        return 0;
    }
    str.ch=new char;
    int i=0,j=0;
    while(i<length){
        if(i>=pos&&j<len){
            str.ch[j]=ch[i];
            j++;
        }
        i++;
    }
    str.length=len;
    return 0; 
}

int main(){
    Str s1("hello");
    Str s2(" world");
    Str target("");
    s1.substring(target,0,4);
    target.readStr(); // hell
    cout<<target.length<<endl; // 4
}

清空串

int Str::clearstring(){
    if(ch){
        ch=NULL;
    }
    length=0;
    return 1;
}

int main(){
    Str s1("hello");
    s1.readStr(); //hello
    s1.clearstring();
    s1.readStr(); // 
    cout<<endl<<s1.length<<endl; // 0
}

串的模式匹配算法

1.簡單模式匹配的算法

基本思想從主串的第一個位置起和模式串的第一個字符開始比較兼贡,如果相等,則繼續(xù)逐一比較后續(xù)字符娃胆。否則從主串兒的第二個字符開始遍希,在重新用上一步的方法與模式串中的字符作比較,以此類推里烦,直到比較完成模式串中所有的字符凿蒜,若匹配成功禁谦,則返回串在主串中的位置,若匹配不成功废封,則返回一個可區(qū)別于主串所有位置的標(biāo)記州泊,如0。

int Str::indexOf(Str target){
    if(length<target.length){
        cout<<"invalid arguments"<<endl;
        return -1;
    }
    int i=0,j=0,k=0; 
    while(i<length&&j<target.length){
        if(ch[i]==target.ch[j]){
            i++;
            j++;
        }else{
            j=0;
            i=++k;
        }
    }
    if(j==target.length){
        return k;
    }
    return -1;
}

int main(){
    Str s1("hello");
    cout<<s1.indexOf("8")<<endl; //-1
    cout<<s1.indexOf("hel")<<endl; // 0
    cout<<s1.indexOf("lo")<<endl; //3
}

2.kmp算法

kmp算法不好理解漂洋,總之重點(diǎn)是求出next數(shù)組遥皂,然后套用簡單匹配模式算法,將j的下一跳置為next[j]就ok了刽漂。具體的算法看博客是不好理解的演训,推薦大家去看視頻。我看的是b站一個印度小哥講解的贝咙,汪都能聽懂的KMP字符串匹配算法【雙語字幕】样悟,他的next數(shù)組與嚴(yán)蔚敏講解的不同,不過很好理解庭猩,我是看書真的看不懂了窟她,(我用19天勤的參考書,跑了遍程序發(fā)現(xiàn)是錯的ORZ)蔼水。下面的算法是拿js實(shí)現(xiàn)的礁苗,按照小哥思路寫的,和書上的next不一樣徙缴,需要你右移一位试伙,每位加1即為嚴(yán)的版本next。

求next數(shù)組

function getNextArr(str) {
  let j = 0, i = 1;
  const next = [0]
  let isSuccessiveEqual = true;
  while (i < str.length && j < str.length) {
    if (str[j] == str[i]) {
      next[i] = isSuccessiveEqual ? (next[i - 1] + 1) : next[j] + 1 
      i++
      j++
      isSuccessiveEqual = true
    } else {
      isSuccessiveEqual = false
      if (j == 0) {
        next[i] = 0
        i++
      } else {
        j = next[j - 1]
      }
    }
  }
  return next
}

getNextArr('abcaby') // [0, 0, 0, 1, 2, 0]
getNextArr('aabaabaaa') // [0, 1, 0, 1, 2, 3, 4, 5, 2]

kmp算法

function kmp(text, pattern) {
  const next = getNextArr(pattern)
  let i = 0, j = 0
  while (i < text.length && j < pattern.length) {
    if (text[i] == pattern[j]) {
      i++
      j++
      if (j == pattern.length) {
        return i - pattern.length
      }
    } else {
      j > 0 ? j = next[j - 1] : i++
    }
  }
  return -1
}

kmp('abxabcabcaby', 'abcaby') // 6
kmp('111str111', 'str11') // 3

關(guān)注訂閱號獲得更加及時的推送~

wechat:那屋水泡
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末于样,一起剝皮案震驚了整個濱河市疏叨,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌穿剖,老刑警劉巖蚤蔓,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異糊余,居然都是意外死亡秀又,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進(jìn)店門贬芥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來吐辙,“玉大人,你說我怎么就攤上這事蘸劈』杷眨” “怎么了?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長贤惯。 經(jīng)常有香客問我洼专,道長,這世上最難降的妖魔是什么孵构? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任屁商,我火速辦了婚禮,結(jié)果婚禮上颈墅,老公的妹妹穿的比我還像新娘蜡镶。我一直安慰自己,他們只是感情好精盅,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著谜酒,像睡著了一般叹俏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上僻族,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天粘驰,我揣著相機(jī)與錄音,去河邊找鬼述么。 笑死蝌数,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的度秘。 我是一名探鬼主播顶伞,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼剑梳!你這毒婦竟也來了唆貌?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤垢乙,失蹤者是張志新(化名)和其女友劉穎锨咙,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體追逮,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡酪刀,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了钮孵。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片骂倘。...
    茶點(diǎn)故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖巴席,靈堂內(nèi)的尸體忽然破棺而出稠茂,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布睬关,位于F島的核電站诱担,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏电爹。R本人自食惡果不足惜蔫仙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望丐箩。 院中可真熱鬧摇邦,春花似錦、人聲如沸屎勘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽概漱。三九已至丑慎,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間瓤摧,已是汗流浹背竿裂。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留照弥,地道東北人腻异。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像这揣,于是被迫代替她去往敵國和親悔常。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內(nèi)容