程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 字符串處理 --- 最小表示法

字符串處理 --- 最小表示法

編輯:C++入門知識

最小表示法:
循環數組中,使用字典序最小的一個序列來表示這個數組。例如A[5] = {5, 1, 3, 2, 4},則最小表示法為{1, 3, 2, 4,5}。

問題:
輸入兩組數據,這兩組數據都是循環數組或者環狀數組,判斷這兩組數據是否一致?

設兩個數組分別為A[],B[]。

解決方案:
正常解題思路:使用兩個for循環進行O(n * n)次判斷即可

KMP方法:將A復制一份加到A後面,然後再A中查找是否存在B字符串,但KMP算法太復雜,難記憶,需要求next[]。

最小表示法,思路一:將A,B都用最小表示法表示出來,然後進行判定

最小表示法,思路二:將A,B各自復制一份加到自己後面,然後具體思路如下:

步驟一:i為A的下標,j為B的下標,k為i和j同時移動的步數,初始化i = 0, j = 0, k = 0.

步驟二:如果A[i] == B[j],k++。如果A[i] > B[j],i = i + k + 1。如果B[j] > A[i],j = j + k + 1。關於為什麼A[i] > B[j] 時,i = i + k + 1。

證明是這樣的,因為A[i] -- > A[i + k] 肯定不為最小表示數,加入再[i, i + k]區間中,存在x是最小表示數,則在B中必然存在B[j + x - i, j + k] < A[x, i + k]。與假設矛盾。

步驟三:如果i < len && j < len && k == len,則兩個數組一致,否則不一致。

算法模板:
[cpp]
/*
測試數據:
69867
76896
*/ 
 
#include <iostream> 
const int nMax = 200; 
char str1[nMax], str2[nMax]; 
char s1[nMax], s2[nMax]; 
 
int main() 

    freopen("e://data.txt", "r", stdin); 
    while(scanf("%s%s", str1, str2) != EOF)//這裡處理的是字符串 
    { 
        bool flag = 0; 
        int len1 = strlen(str1); 
        int len2 = strlen(str2); 
        if(len1 != len2) printf("NO\n");//判斷兩個字符串是否相等 
        memcpy(s1, str1, len1 * sizeof(str1[0]));//將str1復制到s1兩次,結果為s1 = str1 + str1 
        memcpy(s1 + len1, str1, len1 * sizeof(str1[0])); 
        memcpy(s2, str2, len1 * sizeof(str2[0]));//同樣s2 = str2 + str2 
        memcpy(s2 + len2, str2, len1 * sizeof(str2[0])); 
        for(int i = 0, j = 0, k = 0;i < len1 && j < len1 && k < len1;) 
        { 
            if(s1[i + k] == s2[j + k]) ++k; 
            else if(s1[i + k] > s2[i + k]) i = i + k + 1, k = 0; 
            else j = j + k + 1, k = 0; 
            if(k == len1) 
            { 
                flag = 1; 
                break; 
            } 
        } 
        printf("%s\n", flag == 1 ? "YES" : "NO"); 
    } 

 
//最小表示法的另一種運用,直接返回數組s[]中最小表示數 
int getMin(char s[], int len)//s[]也可以定義為其他類型 

    int i = 0,//i,j的初始化有區別 
        j = 1, 
        k = 0; 
    while(i < len && j < len && k < len)//自己與自己比較,A[],B[]都是s[]數組,用i,j對應不同的下標。 
    { 
        int t = s[(i + k) % len] - s[(j + k) % len];//這裡等效於將兩個字符數組s連接起來 
        if(!t)//兩數組相等 
            ++ k; 
        else 
        { 
            if(t > 0) 
                i += k + 1; 
            else 
                j += k + 1; 
            if(i == j)//函數的目的是返回最小表示數,只需要保留i和j中較小的一位即可,所以出現j = j的情況,i++或者j++,繼續匹配 
                i ++; 
        } 
        k = 0; 
    } 
    return i < j ? i : j;//返回i,j中較小的一個 

 


作者:lhshaoren

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved