1. 程式人生 > >程式設計之美-3.1字串移位包含問題

程式設計之美-3.1字串移位包含問題

假設字串s1=AABCD,s2=CDAA,判斷s2是否可以通過S1的迴圈移位得到字串包含。
 如 s1移兩位: 1.ABCDA->2.BCDAA 則此時包含了 S2="CDAA"


 解題思路:
 分解s1的迴圈移位得到:
 AABCD,ABCDA,BCDAA,CDAAB,.....
 如果我們將前面移走的字串保留下來,則有:
 AABCD,AABCDA,AABCDAA,AABCDAAB,AABCDAABC,AABCDAABCD

這裡,我們可以發現,實際對s1的迴圈移位得到的字串實際為s1s1。
那麼我們判斷s2是否可以通過s1迴圈移位得到包含,則只需要判斷s1s1中是否含有s2即可以。
用提高空間複雜度來換取時間複雜度的減低的目的。

 

     函式名: strstr
    包含檔案:string.h  函式原型:extern char *strstr(char *str1, char *str2);   功能:找出str2字串在str1字串中第一次出現的位置(不包括str2的串結束符)。

  返回值:返回該位置的指標,如找不到,返回空指標。
其引數是傳統的char   *型字串,string型資料型別是不能作為其引數的。但可以通過string成員函式string::c_str()轉換成char*型別。象這樣呼叫: 
strstr(str1.c_str(),   str2.c_str())  

#include<iostream>
#include<string>

using namespace std;

bool rotstr(string src,string des)
{
    string tmp = src;
    src=src+tmp;
    if(strstr(src.c_str(),des.c_str())==NULL)
    {
        return false;
    
    }

    return true;

}

int main()
{
    string src="AABBCD";
    string des="DAAB";
    if(rotstr(src,des))
        cout<<"the string des is included in the rotated string of src "<<endl;
    else
        cout<<"the string des is not included in the rotated string of src "<<endl;
    return 0;
}


擴充套件:

找出s2中第一個字元在s1的位置記為p1,找出s2中最後一個字元在s1中可能的位置記為p2,計算所有的p1與p2間的差值,若等於s2的長度,則比較p1與p2間的字串與s2,若兩者相等則返回true,否則返回false

#include<iostream>
#include<string>
#include<vector>
using namespace std;

bool rotstr(string src,string des)
{
    //用vecPos1儲存dest字串第一個字元在src中可能出現的位置
    //用vecPos2儲存dest字串最後一個字元在src中可能出現的位置
    vector<int> vecPos1;
    vector<int> vecPos2;
    string str=src;
    int substrpos=str.find(des[0]);
    int pos=substrpos;
    //pos為字元在字串中的位置
    while(substrpos!=-1)
    {
        cout<<pos<<endl;
        vecPos1.push_back(pos);
        str=src.substr(pos+1,src.length()-pos-1);
        substrpos=str.find(des[0]);
        pos=pos+1+substrpos;
    }
    str=src;
    substrpos=str.find(des[des.size()-1]);
    pos=substrpos;
    while(substrpos!=-1)
    {
        cout<<pos<<endl;
        vecPos2.push_back(pos);
        str=src.substr(pos+1,src.length()-pos-1);
        substrpos=str.find(des[des.size()-1]);
        pos=pos+1+substrpos;
    }
    int p1,p2;
    int len;
    string s;
    for(int i=0;i<vecPos1.size();i++)
    {
        for(int j=0;j<vecPos2.size();j++)
        {
            p1=vecPos1[i];
            p2=vecPos2[j];
            //最後一個字元出現在第一個字元前
            if((p2-p1)<0)
                len=src.size()-p1+p2+1;
            //最後一個字元出現在第一個字元後
            else
                len=p2-p1+1;
            if(len==des.size())
            {
                if(p2-p1>=0)
                    s=src.substr(p1,p2-p1+1);
                else
                    s=src.substr(p1,src.size()-p1)+src.substr(0,p2+1);
                if(s==des)
                {
                    return true;
                }

            }
        }
    }
    return false;
}

int main()
{
    string src="AABBCD";
    string des="DAAB";
    if(rotstr(src,des))
        cout<<"the string des is included in the rotated string of src "<<endl;
    else
        cout<<"the string des is not included in the rotated string of src "<<endl;
    int i;
    cin>>i;
    return 0;
}

PS:

檢測兩個字串是否相等
對於C:strcmp(str1,str2)==0

對於C++: str1==str2
               原因:C++string類過載了==運算子以便檢測字串的內容是否相等

對於java:str1.equals(str2)
                說明:java中也有str1==str2 但是表達的含義不同
                java的物件變數與c++不同,java的物件變數可以看做C++的指標
                如:Date birth;      //java
                   等價於:Date * birth; // c++
               所以str1==str2 是判斷兩個指標所指向的地址是否相同,而不是指標所指向的內容是否相同
               所以java中檢測兩個字串是否相等用:str1.equals(str2)或者:str1.compareTo(str2)