HDU 2668 Daydream(最长不重复子序列)

题目描述:
Daydream
Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u

Description
Welcome to 2009 HDU Girl’s Cup, bless you will happy in it.
Every girl are beautiful if you use you heart to feel. Every corner in the world will colourful and energetic by several girls standing. If you boy, a normal bay, I believe that you will try to watch when a beautiful girl passing you and you will nervous if a girl watching you just when you are watching her.

Now give you a surprise that may be never happy in the real time. Millions of PLMM stand in a line and facing you(^_^). They are dress colourful clothings. You should to find out a maximal subline PLMM that their clothing color are all different.

Input
The input contains multiple test cases.
Each case first give a integer n expressing many many girls stand in line.(n<=10000000)
Next line a string including n character, each character standing one girls’s clothing color.

Output
Output one integer the numbers of maximal subline PLMM that their clothing color are all different and the line’s begin and end (based from 0). If their are more answer, print the begin smallest.

Sample Input

3
abc
5
aaaba
8
hdugirls

Sample Output

3 0 2
2 2 3
8 0 7

题目大意:
就是问你给定的序列中最长的连续的不重复的子序列的长度,以及起始位置,如果有多处,输出最前面的一组

题目分析:
首先看数据规模,10^7,至少要搞到o(n)的时间复杂度,先说明一点,题目说的是字符,但是并没有说是小写字母,尽管样例都是小写,所以数组开大点,150或者300都行,接下来说思路,感觉思路就是尺取法,两个指针,一个定在开始,另外一个开始往前扫,把出现的字母的位置存在刚才开的数组里,直到出现重复为止(数组的这个位置已经放过字符)那么这时候就把当前扫描的序列的长度以及起始位置跟原来比较一下,留下长的序列,然后把后面的指针挪到重复的字符的位置的下一个字符。值得注意的一点是,我们并不需要每次在扫描最长的序列之前都对数组进行一次重新赋值,只需要看重复的字符是不是在当前尾指针的右侧(左侧的话跟当前扫描没关系)

代码:

#include "cstdio"
#include "cstring"
int pos[150];
int main()
{
    int n,i,l,r,ltmp,cnt,cnttmp;
    char ch;
    while(scanf("%d",&n)!=EOF)
    {
        getchar();
        ch=getchar();
        cnt=ltmp=0;
        cnttmp=1;
        memset(pos,-1,sizeof(pos));
        pos[ch]=0;
        for(i=1;i<n;i++)
        {
            ch=getchar();
            //出现重复
            if(pos[ch]>=0&&pos[ch]>=ltmp){
                if(cnttmp>cnt){
                    cnt=cnttmp;
                    l=ltmp;
                    r=i-1;
                }
                cnttmp-=pos[ch]-ltmp;
                ltmp=pos[ch]+1;
            }else{
                cnttmp++;
            }
            //不管重不重,都把最新出现的位置放过来
        //因为只有新位置才会影响以后,旧位置的话一定在尾指针之前,没用了
            pos[ch]=i;
        }
        if(cnttmp>cnt){
            cnt=cnttmp;
            l=ltmp;
            r=i-1;
        }
        printf("%d %d %d\n",cnt,l,r);
    }
    return 0;
}
### HDU 1159 最长公共子序列 (LCS) 解题思路 #### 动态规划状态定义 对于两个字符串 `X` 和 `Y`,长度分别为 `n` 和 `m`。设 `dp[i][j]` 表示 `X[0...i-1]` 和 `Y[0...j-1]` 的最长公共子序列的长度。 当比较到第 `i` 个字符和第 `j` 个字符时: - 如果 `X[i-1]==Y[j-1]`,那么这两个字符可以加入之前的 LCS 中,则有 `dp[i][j]=dp[i-1][j-1]+1`[^3]。 - 否则,如果 `X[i-1]!=Y[j-1]`,那么需要考虑两种情况中的最大值:即舍弃 `X[i-1]` 或者舍弃 `Y[j-1]`,因此取两者较大者作为新的 LCS 长度,即 `dp[i][j]=max(dp[i-1][j], dp[i][j-1])`。 时间复杂度为 O(n*m),其中 n 是第一个字符串的长度而 m 是第二个字符串的长度。 #### 实现代码 以下是 Python 版本的具体实现方式: ```python def lcs_length(X, Y): # 初始化二维数组用于存储中间结果 m = len(X) n = len(Y) # 创建(m+1)x(n+1)大小的表格来保存子问题的结果 dp = [[0]*(n+1) for _ in range(m+1)] # 填充表项 for i in range(1, m+1): for j in range(1, n+1): if X[i-1] == Y[j-1]: dp[i][j] = dp[i-1][j-1] + 1 else: dp[i][j] = max(dp[i-1][j], dp[i][j-1]) return dp[m][n] # 测试数据输入部分可以根据具体题目调整 if __name__ == "__main__": while True: try: a = input().strip() b = input().strip() result = lcs_length(a,b) print(result) except EOFError: break ``` 此程序会读入多组测试案例直到遇到文件结束符(EOF)。每组案例由两行组成,分别代表要计算其 LCS 的两个字符串。最后输出的是它们之间最长公共子序列的长度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值