字符串算法总结

  • 数字转字符串
  • 字符串逆置(char*、string、折半法逆置字符串、异或法逆置字符串)
  • 字符串逆置保持单词不变
  • 实现strcpy,strcat,strcmp,strstr
  • 最长公共子串(这个博客里讲的比较好,这里我只是自己实现了一下,子串我的博客里已经讲过了 http://blog.sina.com.cn/s/blog_54f82cc20100zi4b.html
  • 最长公共子序列(和子串很像,只是状态转移公式不太一样:字符相等arr[i][j]=arr[i-1][j-1]+1;/字符不等arr[i][j]=max(arr[i][j-1],arr[i-1][j]);然后返回arr[len1][len2]就是最长公共子序列的长度;)
  • 回文串(和逆置后的字符串是否相等,leetcode有道很难的最短回文串的题目,是加最少的字符使其成为回文串214. Shortest Palindrome博客里有总结,是利用了KMP里的next数组)
  • 字符串最后一个单词的长度(华为OJ上的题热门第一- -|||,cin以空格为结束,所以用getline读取字符串,然后从最后找到空格,length减去找到空格的下标减一即可,当然我是用循环做的,为什么都是90分!!怒)
  • 大数加法(字符串加法)
  • 大数乘法(字符串减法)

 

 

#include<iostream>
#include<string>
#include<assert.h>
#include <vector>
#include <algorithm>
using namespace std;


//数字转字符串
string InttoChar(int num) {
    if (num == 0)
        return "0";
    string res;
    while (num != 0) {
        int tmp = num % 10;
        char ctmp = tmp + '0';
        res.push_back(ctmp);
        num /= 10;
    }
    reverse(res.begin(), res.end());
    return res;
}
//字符串逆置
string reversestring(string s1) {
    if (s1 == "")
        return s1;
    string s2 = "";
    for (int i = s1.length() - 1; i >= 0; i--) {
        s2 += s1[i];
    }
    return s2;
}
//折半法逆置字符串
char* revetsestring(char* s1) {
    if (s1 == NULL)
        return s1;
    int len = strlen(s1);
    char* p1, *p2;
    p1 = s1, p2 = s1 + len - 1;
    char tmp;
    while (p1 != p2) {
        tmp = *p1;
        *p1 = *p2;
        *p2 = tmp;

        p1++;
        p2--;
    }
    return s1;
}
//异或法逆置字符串
char* revetsestr(char* str) {
    if (str == NULL)
        return str;
    char* f = str, *b = str + strlen(str) - 1;
    while (f<b) {
        *f ^= *b;
        *b ^= *f;
        *f ^= *b;
        f++;
        b--;
    }
    return str;
}
//字符串逆置单词内部顺序不变
char* ReverseWords(char* s1) {
    int len = strlen(s1);
    if (s1 == NULL || len == 1)
        return s1;
    int i = len - 1, j = len;  //ij记录单词的位置
    int t = 0; //暂存已经录入单词的位置
    char* res = new char[len + 1]; //len不包含'\0'要申请len+1个
    int k = 0;  //新字符串的位置
    while (i>0) {
        while (s1[i] != ' '&&i != 0)
            i--;
        t = i;
        if (i != 0)
        {
            i++;
            while (i<j) {
                res[k++] = s1[i++];
            }
            res[k++] = ' ';
            j = t;
            i = t - 1;
        }
        else {
            while (i<j)
            {
                res[k++] = s1[i++];
            }
            i = t;
        }

    }
    res[len] = '\0';
    return res;
}

//分别实现strcpy,strcat,strcmp,strstr
//strcpy需要一个指针记录开始的位置
char* stringcpy(char* des, char* src) {
    if (src == NULL)
        return src;
    int len = strlen(src);
    des = new char[len + 1];
    char* res = des;
    while (*src != '\0')
        *des++ = *src++;
    *des = '\0';
    return res;
}


//strcat,strcat需要des保证可以容纳src,我们这里不需要
char* stringcat(char* des, char*src) {
    if (src == NULL)
        return des;
    int len1 = strlen(des);
    int len2 = strlen(src);
    char* newstr = new char[len1 + len2 + 1];
    char* res = newstr;
    while (*des != '\0')
        *newstr++ = *des++;
    while (*src != '\0')
        *newstr++ = *src++;
    *newstr = '\0';
    return res;
}


//strcmp,使用assert要包含其头文件assert.h不满足assert条件会报错
int stringcmp(char* s1, char* s2) {

    assert((s1 != NULL) && (s2 != NULL));
    while (*s1&&*s2 && (*s1 == *s2)) {
        s1++;
        s2++;
    }
    return *s1 - *s2;
}

//strstr leetcode有原题,做过
bool samestr(char* s1, char* s2) {
    if (strlen(s1) != strlen(s2))
        return false;
    while (*s1) {
        if (*s1 == *s2) {
            s1++;
            s2++;
        }
        else return false;
    }
    return true;
}
char* stringstr(char* s1, char* s2) {
    if (s1 == NULL || s1 == NULL)
        return NULL;
    int len1 = strlen(s1);
    int len2 = strlen(s2);
    if (len2>len1)
        return NULL;
    if (len1 == len2) {
        if (samestr(s1, s2))
            return s1;
        else return NULL;
    }

    for (int i = 0; i<len1;) {
        char* tmp = NULL;
        for (int j = 0; j<len2; j++)
            tmp += s1[i + j];
        tmp += '\0';
        if (samestr(tmp, s2))
            return s1 + i;
        else i++;
    }
    return NULL;
}
//最长公共子串
string MaxSubstring(string& s1, string& s2) {
    if (s1 == "" || s2 == "")
        return "";
    int len1 = s1.length();
    int len2 = s2.length();

    int arraystr[100][100] = { 0 };//then the max length of string is 1000
    for (int i = 0; i<len1; i++) {
        for (int j = 0; j<len2; j++) {
            if (s1[i] == s2[j])
            {
                if (i == 0 || j == 0)
                    arraystr[i][j] == 1;
                else arraystr[i][j] = arraystr[i - 1][j - 1] + 1;
            }
            else arraystr[i][j] = 0;
        }
    }

    int maxlen = 0;
    int maxindex = 0;
    for (int i = len1 - 1; i >= 0; i--) {
        for (int j = len2 - 1; j >= 0; j--) {
            if (arraystr[i][j]>maxlen) {
                maxlen = arraystr[i][j];
                maxindex = j;
            }
        }
    }
    string res = "";
    for (int k = maxindex - maxlen + 1; k <= maxindex; k++)
        res += s2[k];
    return res;
}
//最长公共子序列长度
int Maxsubsequencelength(string& s1, string& s2) {
    if (s1 == "" || s2 == "")
        return 0;
    int arraystr[1010][1010] = { { 0,0 } };
    int len1 = s1.length();
    int len2 = s2.length();

    for (int i = 1; i <= len1; i++) {
        for (int j = 1; j <= len2; j++) {
            if (s1[i - 1] == s2[j - 1])
                arraystr[i][j] = arraystr[i - 1][j - 1] + 1;
            else arraystr[i][j] = max(arraystr[i - 1][j], arraystr[i][j - 1]);
        }
    }
    return arraystr[len1][len2];
}


string Maxsubsequence(string& s1, string& s2) {   //输入时字符串长的那个为第一参数
    string res = "";
    if (s1 == "" || s2 == "")
        return res;
    int arraystr[100][100] = { { 0,0 } };
    int len1 = s1.length();
    int len2 = s2.length();

    for (int i = 1; i <= len1; i++) {
        for (int j = 1; j <= len2; j++) {
            if (s1[i - 1] == s2[j - 1])
                arraystr[i][j] = arraystr[i - 1][j - 1] + 1;
            else arraystr[i][j] = max(arraystr[i - 1][j], arraystr[i][j - 1]);
        }
    }

    for (int i = len1; i >= 0;) {
        for (int j = len2; j >= 0;) {
            if (arraystr[i][j]>max(max(arraystr[i - 1][j], arraystr[i][j - 1]), arraystr[i - 1][j - 1])) {
                res = s1[i] + res;
                i--;
                j--;
            }
            else {
                if (arraystr[i][j] == arraystr[i - 1][j - 1]) {
                    i--;
                    j--;
                }
                else if (arraystr[i][j] == arraystr[i - 1][j])
                    i--;
                else if (arraystr[i][j] == arraystr[i][j - 1])
                    j--;
            }
        }
    }
    return res;
}

//最后一个单词的长度
int lastword(string s1) {
    if (s1 == "")
        return 0;
    int len = s1.length();
    int i = len - 1;
    int res = 0;
    while (i >= 0 && s1[i] == ' ') {
        i--;
    }
    while (i >= 0 && s1[i] != ' ') {
        i--;
        res++;
    }
    return res;
}
int lastwordlen(string s1) {
    getline(cin, s1);
    if (s1 == "")
        cout << 0 << endl;
    return s1.length() - s1.rfind(' ') - 1;

}
//回文串
bool isPalindrome(string s1) {
    string s2 = s1;
    reverse(s2.begin(), s2.end());
    if (s1 == s2)
        return true;
    else return false;

}
//字符串大数加法
string stringadd(string& s1, string& s2) {
    int len1 = s1.length();
    int len2 = s2.length();
    if (len1 == 0)
        return s2;
    if (len2 == 0)
        return s1;

    int mlen = max(len1, len2);

    int* arr1 = new int[mlen];//把字符串数字转换成数组存储,在进行加和然后转成字符串
    int* arr2 = new int[mlen];
    int index = mlen - 1;
    for (int i = len1 - 1, j = len2 - 1; i >= 0 || j >= 0; index--) {
        if (i >= 0)
            arr1[index] = s1[i--] - '0';
        else arr1[index] = 0;
        if (j >= 0)
            arr2[index] = s2[j--] - '0';
        else arr2[index] = 0;
    }

    int* res = new int[mlen + 1];
    int carr = 0;
    int k = mlen - 1, l = mlen;
    while (k >= 0) {
        int tmp = arr1[k] + arr2[k] + carr;
        carr = tmp / 10;
        res[l--] = tmp % 10;
        k--;
    }
    if (carr != 0)
        res[0] = carr;
    else res[0] = 0;
    string ret = "";
    for (int i = 0; i <= mlen; i++) {
        if (res[i] == 0)
            continue;
        char c = '0' + res[i];
        ret = ret + c;

    }
    return ret;
}
//字符串大数乘法
char* MultiString(char* str1, char* str2) {

    int len1 = strlen(str1), len2 = strlen(str2);
    if (len2>len1) {              //len1,str1对应较长的字符串
        char* temp = str1;
        int temp1 = len1;
        str1 = str2;
        str2 = temp;
        len1 = len2;
        len2 = temp1;
    }

    char* ret = new char[len1 + len2];
    memset(ret, '0', sizeof(char)*(len1 + len2 - 1));  //初始化字符串
    ret[len1 + len2 - 1] = '\0';

    if (len1 == 0 || len2 == 0)
        return ret;
    int temp1 = 0, temp2 = 0;
    for (int i = len2 - 1; i >= 0; i--) {
        int carry = 0;
        for (int j = len1 - 1; j >= 0; j--) {
            int sum = ret[i + j] - '0';
            if (carry>0)
                sum += carry;
            temp1 = str1[j] - '0';
            temp2 = str2[i] - '0';
            sum += temp1*temp2;
            if (sum >= 10) {
                carry = sum / 10;
            }
            else carry = 0;
            ret[i + j] = sum % 10 + '0';  //规格化处理
            if (j == 0 && carry>0)    //最高位以后还有可能进位
                ret[i - 1] += carry;
        }
        cout << i << "    " << ret << endl;
    }

    char* p = ret;
    while (*p == '0')   //如果前面有0,从第一位不是0开始输出
        p++;
    cout << p << endl;
    return p;
}




int main() {
    int num = 1234569;
    string res = InttoChar(num);
    cout << res << endl;

    char* test = "guofei is a student in SEU!";
    string test1 = "helloworld";
    char* test2 = "happyforever";
    cout << reversestring(test2) << endl;
    cout << reversestring(test1) << endl;
    cout << ReverseWords(test) << endl;

    char* s1, *s2 = "cpy this string";
    cout << stringcpy(s2, s2) << endl;
    cout << stringcmp(test, test2) << endl;

    char* s3 = "auti";
    char* s4 = "beautiful girl";
    if (stringstr(s3, s4))
        cout << "fei zi chuan" << endl;
    else cout << "zichuan" << endl;  //his problem is really tricky, i try to cout NULL and i fix bug just for this little error makes me very wordless

    string s5 = "ade";
    string s6 = "abcde";
    string res1 = MaxSubstring(s5, s6);
    cout << res1 << endl;
    cout << Maxsubsequence(s6, s5) << endl;

    string s7 = "accba";
    cout << isPalindrome(s7) << endl;
    return 0;
}

 

posted @ 2016-08-10 23:15  0giant  阅读(2810)  评论(0编辑  收藏  举报