java字符串里有两个重复字符我想删掉其中一个

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java字符串里有两个重复字符我想删掉其中一个相关的知识,希望对你有一定的参考价值。

可以用public String substring(int beginIndex , int endIndex)方法

该方法可以获取介于beginIndex和endIndex之间的子字符串

把一个字符串的后两个字母去掉:  s=s.substring(0,s.length()-2);

例如:

参考技术A 在我留言下的评论里留下你的邮箱,回头发给你

字符串距离问题

到目前为止,我团队赛打的很少,但有好几次团队赛都出现了字符串距离问题,作个整理。

经典的字符串距离问题,求两字符串之间的距离,两个字符串之间的距离指的是至少通过多少次操作使得这两个字符串相同。

有两个操作:

1 :选其中一个字符串,在其任意位置插入一个任意字符;

2: 选其中一个字符串,删掉其中任意一个字符。

样例输入:

aabd

ad

样例输出 :

2

 

做法一:正着求,用递推的方法推出,dp[i][j]表示A[1,2...i]和B[1,2...j]的距离

    for(int i = 1;i <= len_a;i++){
        for(int j = 1;j <= len_b;j++){
            if(a[i] == b[j]) {
                dp[i][j] = dp[i-1][j-1];
            }
            else dp[i][j] = min(dp[i-1][j],dp[i][j-1])+1;
        }
    }
    ans = dp[len_a][len_b];

 

做法二:先求出两个串的LCS(最长公共子串的长度),距离=两串长度和-2*LCS

    for(int i = 1;i <= len_a;i++){
        for(int j = 1;j <= len_b;j++){
            if(a[i] == b[j]) {
                lcs[i][j] = lcs[i-1][j-1]+1;
            }
            else lcs[i][j] = min(lcs[i-1][j],lcs[i][j-1]);
        }
    }
    ans = len_a+len_b-2*lcs[len_a][len_b];

我的第一次团队赛碰到了这样一题:

技术图片技术图片

给两串字符串,含若干字母和数字,求使两个字符串相同且不含数字所需的最少操作数

操作一:任选一个字母插入到任意位置

操作二:任选一个字母删掉

操作三:把数字换成对应个数的任意字母

 

先把所有数字都展开成对应个数的‘#‘, ‘#‘可以和任意字母对应

这就转换成了求两串字符串的差距问题,正着求差距,或者先求最长公共字串都行

#include<iostream>
#include<algorithm>
using namespace std;
long long dp[12000][3000];
int main()
{
    long long res = 0;
    string a,b,s1,s2;
    s1 = "",s2="";
    cin>>a>>b;
    int lena = a.length();
    int lenb = b.length();
    for(int i = 0;i<lena;i++){
        if(a[i]<=9&&a[i]>=0){
            int x = a[i]-0;
            for(int j =1;j<=x;j++) s1+=#;
            res++;
        }
        else s1+=a[i];
    }
    for(int i = 0;i<lenb;i++){
        if(b[i]<=9&&b[i]>=0){
            int x = b[i]-0;
            for(int j =1;j<=x;j++) s2+=#;
            res++;
        }
        else s2+=b[i];
    }
    //cout<<s1<<endl<<s2<<endl;
    int len1 = s1.length();
    int len2 = s2.length(); 
    dp[0][0] = 0;
    for(int i =1;i<=len1;i++) dp[i][0] = i;
    for(int i = 1;i<=len2;i++) dp[0][i] = i;
    for(int i =1;i<=len1;i++){
        for(int j =1;j<=len2;j++){
            if(s1[i-1]==s2[j-1]||s1[i-1]==#||s2[j-1]==#) dp[i][j] = dp[i-1][j-1];
            else dp[i][j] = min(dp[i-1][j],dp[i][j-1])+1;
        }
    }
    cout<<dp[len1][len2]+res<<endl;
    return 0;
}

2020杭电多校第二场1012:

给两个串A和B,A长为n,B长为m,q次查询,每次查询给一个L,R区间,求A[L...R]和B[1...m]的距离

T组输入,T<=10,n<=1e5,m<=20,q<=1e5,1<=L<=R<=n。

看起来很难,关键抓住m很小,A[L,R]和B[1...m]的LCS<=m<=20,也就是LCS的取值范围很小,之前是用递推求出A[1...i]和B[1...j]的答案,然而这个答案的取值范围却这么小,我们可以用答案反推,其中一个串取[1...i],LCS=j时,另一个串至少要取到多少,这也是可以递推的。

L,R区间是多变的,每次查询,我们就递推一遍,f[ i ][ j ]的意义:B串取[1...i],LCS = j时,A至少要从L取到f[ i ][ j ]。

为了能够递推,首先还要预处理一个东西:g[ i ][ j ] :A[i...n]中字符 j 第一次出现的位置,若其一次都不出现就为INF

g数组可以从后往前递推得到

        for(int j = 0;j < 26;j++) g[n+1][j] = INF;
        for(int i = n;i ;i--){
            for(int j = 0;j < 26;j++){
                g[i][j] = g[i+1][j];
            }
            g[i][A[i]-a] = i;
        }

得到g数组后,f数组就可以递推了

f[ i ][ j ] = min(f[ i - 1 ][ j ],g[  f [ i - 1 ][ j - 1 ]+1 ][  B [ i ] -  ‘a‘ ] )

AC代码:wa了好多发才过qwq

#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int MAXN = 1e5+7;
const int INF = 1e9+9;
int g[MAXN][26];
int f[21][21];
int main()
{
    int T,n,m,q,l,r;
    string A,B;
    cin>>T;
    while(T--){
        cin>>A>>B;
        n = A.length();
        m = B.length();
        A =" "+A;
        B =" "+B;
        for(int j = 0;j < 26;j++) g[n+1][j] = INF;
        for(int i = n;i ;i--){
            for(int j = 0;j < 26;j++){
                g[i][j] = g[i+1][j];
            }
            g[i][A[i]-a] = i;
        }
        cin>>q;
        while(q--){
            scanf("%d%d",&l,&r);
            f[0][0] = l-1;//起点 
            for(int i = 1;i <= m;i++){
                f[i][0] = l-1;//起点 
                for(int j = 1;j <= i && j <= n;j++){
                    if(j==i){
                        if(f[i-1][j-1]>= r) f[i][j] = INF;
                        else f[i][j] = g[f[i-1][j-1]+1][B[i]-a];
                    }
                    else {
                        if(f[i-1][j-1]>= r) f[i][j] = INF;
                        else f[i][j]=min(f[i-1][j],g[f[i-1][j-1]+1][B[i]-a]);
                    }
                }
            }
            int gg = 0;
            for(int j = 1;j <= m && j <= n;j++){
                if(f[m][j]<=r) gg = j;
                else break;
            }
            printf("%d
",r-l+1+m-2*gg);
        }
    }    
    return 0;
}

 

以上是关于java字符串里有两个重复字符我想删掉其中一个的主要内容,如果未能解决你的问题,请参考以下文章

java 写一个方法,这个方法里有两个参数,并且没有返回值

Android 系统APK-计算器 修复按一次Backspace键会删掉两个字符

Java,计算两个日期之间的天数[重复]

如何在 JavaScript 中连接两个不重复的字符串 [重复]

3. 无重复字符的最长子串 4. 寻找两个正序数组的中位数 java

Android 11.0 修复在计算器APK(Calculator),按一次Backspace键会删掉两个字符