hihocoder 1323 텍스트 문자열 구간 dp OR 기억화 검색

2031 단어 dp구간 dp
제목 링크

묘사


문자열 S를 지정하려면 최소한 몇 번의 삭제 작업이 필요합니다. S를 메모 문자열로 바꿀 수 있습니까?
한 번에 임의의 위치에 문자를 삽입하거나, 임의의 문자를 삭제하거나, 임의의 문자를 임의의 다른 문자로 수정할 수 있다.
아이디어:
기억화 검색을 고려하면 dp[l][r]는 l에서 r로 끝나는 문자열이 메모열을 구성하는 데 필요한 최소 작업 횟수를 나타낸다.
1. 만약에 s[l]=s[r]dp[l][r]=dp[l+1][r-1];
2.만약s[l]!=s[r]그러면 우리는 문자를 추가하고, 문자를 삭제하고, 문자를 수정하는 것을 고려해야 한다.문자를 삭제하고 추가하는 것이 사실 등가임을 감안하면
네, 여기 첨가만 할게요.
  dp[l][r] = min(dp[l+1][r],dp[l][r-1],dp[l+1][r-1])+1
dp[l+1][r]는 s[r] 뒤에 s[l] 문자가 일치하는 것을 표시합니다
pp[l][r-1]는 s[1] 앞에 s[r] 문자가 일치하는 것을 나타낸다
pp[l+1][r-1]는 s[l]s[r] 중 하나를 다른 것으로 수정하는 것을 나타낸다.
#include   
using namespace std;  
const int N = 105;  
int dp[N][N];  
char s[N];
int min(int a, int b, int c)  
{  
    return min(min(a, b), c);  
}  
int dfs(int l,int r)
{
	if(l >= r) return dp[l][r] = 0;
	if(dp[l][r] != -1) return dp[l][r];
	if(s[l] == s[r])
	return dp[l][r] = dfs(l+1,r-1);
	return dp[l][r] = 1+min(dfs(l+1,r),dfs(l,r-1),dfs(l+1,r-1));
}
int main()  
{  
    
    scanf("%s",s+1);
    int len = strlen(s+1);  
    memset(dp, -1, sizeof(dp));  
    dfs(1,len);
    cout<

물론 구간 dp도 가능하지만 사실은 위의 본질과 똑같다. 모두 가장 작은 (두 글자마다)로 회문을 구성하고 크게 확장한다.
#include 
#include 
#include 
using namespace std;
char s[105];
int dp[105][105];
int min(int a,int b,int c)
{
	return min(a,min(b,c));
}
int main()
{
    scanf("%s", s);
    int n = strlen(s);
    for(int len = 2; len <= n; len++)
    {
        for(int i = 0; i + len - 1 < n; i++)
        {
            int j = i + len - 1;
            if(s[i] == s[j])
                dp[i][j] = dp[i+1][j-1];
            else
                dp[i][j] = min(dp[i+1][j],dp[i][j-1],dp[i+1][j-1]) + 1;
        }
    }
    printf("%d
", dp[0][n-1]); return 0; }

좋은 웹페이지 즐겨찾기