Leetcode-3 看错题目系列

  最长公共子串和最长公共子序列都是非常简单的动态规划问题。

  都使用dp[i][j],都是O(n^2)的时间复杂度。

  第一个状态转移方程为:dp[i][j]=0; 如果s[i]!=s[j]

             dp[i][j]=dp[i-1][j-1]+1,如果s[i]==s[j]

             就是表示都要以i,j结尾的子串,最长的公共子串长度

  第二个状态转移方程,dp[i][j]表示无限制的子序列最长长度

            如果s[i]==s[j],dp[i][j]=dp[i-1][j-1]+1

            否则就继承前面,dp[i][j]=max(dp[i-1][j],dp[i][j-1]);

 

  傻逼了,就是一道滑动窗口傻逼题。

  不过这题还是有独到之处的,那就是字符不是简单的小写英文字母,而是可以是任意字符

,这就使得我第一次写的时候overflow了。

  让后才回忆起来一个知识:C语言中,char转int输出的时候,直接输出的是asc2值。

 

顺便过了几个月第一次再做这个傻逼题的时候还做错了

class Solution
{
public:
    unordered_map<char,int>mp;
    int id_cnt=0;
    int getid(const char &c)
    {
        if(!mp.count(c))
        {
            mp[c]=id_cnt++;
        }
        return mp[c];
    }
    int lengthOfLongestSubstring(string s)
    {
        if(s=="")return 0;
        int res=1;//显然答案的最小值为1
        bool vis[130];
        memset(vis,false,sizeof(vis));

        int len=s.length();
        int l=0,r=1;
        vis[getid(s[l])]=true;

        while(l<len&&r<len)
        {
            int x=getid(s[r]);
            if(vis[x])//如果右边新加上来的这个东西会破坏原来的结构
            {
                //那么解决办法是l指针一直往右,直到消去
                while(l<len)
                {
                    if(getid(s[l])==x)//说明当前指向就是r指向的值
                    {
                        l++;
                        break;
                    }
                    l++;
                }
                r++;
                //冲突了必然不可能有答案更新
            }
            else
            {
                vis[x]=true;
                res=max(res,r-l+1);
                r++;
            }
        }
        return res;
    }
};

  不过事实也说明leetcode是可以自己加函数的。

  不过问题的关键不在这里,而是

  "tmmzuxt"输出4,预期结果为5

  原因是左指针移动时没有消去原来的vis,本质上还是滑动窗口不熟练

 

AC代码

#include<bits/stdc++.h>
using namespace std;
class Solution
{
public:
    unordered_map<char,int>mp;
    int id_cnt=0;
    int getid(const char &c)
    {
        if(!mp.count(c))
        {
            mp[c]=id_cnt++;
        }
        return mp[c];
    }
    int lengthOfLongestSubstring(string s)
    {
        if(s=="")return 0;
        int res=1;//显然答案的最小值为1
        bool vis[130];
        memset(vis,false,sizeof(vis));

        int len=s.length();
        int l=0,r=1;
        vis[getid(s[l])]=true;

        while(l<len&&r<len)
        {
            int x=getid(s[r]);
            if(vis[x])//如果右边新加上来的这个东西会破坏原来的结构
            {
                //那么解决办法是l指针一直往右,直到消去
                while(l<len)
                {
                    if(getid(s[l])==x)//说明当前指向就是r指向的值
                    {
                        l++;
                        break;
                    }
                    vis[getid(s[l])]=false;
                    l++;
                }
                r++;
                //冲突了必然不可能有答案更新
            }
            else
            {
                vis[x]=true;
                res=max(res,r-l+1);
                r++;
            }
        }
        return res;
    }
};
int main()
{
    Solution s;
    cout<<s.lengthOfLongestSubstring("tmmzuxt")<<endl;
    return 0;
}

 

  

  

  

 

  

posted @ 2021-02-05 00:05  TheDa  阅读(44)  评论(0编辑  收藏  举报