很明顯的區間dp,設dp[l][r]表示[l,r]區間的字串摺疊後的最小長度。
可以通過兩種方向轉移,dp[l][r]=min(dp[l][i]+dp[i+1][r]).
另一種是摺疊,dp[l][r]=min(dp[l][l+k-1]+cal((r-l+1)/k)+2).其中k是能整除(r-l+1)的數且區間能夠摺疊成k份,cal()函式計算數字的位數。
另外用了線段樹維護hash值,可以每次驗證logn。
# include # includeview code# include
# include
# include
# include
# include
# include
# include
# include
# include
using
namespace
std;
# define lowbit(x) ((x)&(-x))
# define pi acos(-1.0
)# define eps 1e-8
# define mod
1000000007
# define inf
1000000000
# define mem(a,b) memset(a,b,
sizeof
(a))
# define for(i,a,n)
for(int i=a; i<=n; ++i)
# define fo(i,a,n)
for(int i=a; ii)
# define bug puts("h
");# define lch p
<<1
,l,mid
# define rch p
<<1|1,mid+1
,r# define mp make_pair
# define pb push_back
typedef pair
pii;
typedef vector
vi;# pragma comment(linker,
"/stack:1024000000,1024000000")
typedef
long
long
ll;int
scan()
void out(int
a)
if(a>=10) out(a/10
); putchar(a%10+'0'
);}const
int n=105;//
code begin...
char
s[n];
intdp[n][n], n;
ll seg[n
<<2
], power[n];
void push_up(int p, int l)
void init(int p, int l, int
r) seg[p]=s[l];
}ll query(
int p, int l, int r, int l, int
r)int qiu(int
x)int cal(int l, int r, int
k)
if (!flag) return
inf;
else
return dp[l][l+k-1]+qiu((r-l+1)/k)+2;}
int dfs(int l, int
r)int
main ()
bzoj1090 字串摺疊
問題描述 摺疊的定義如下 1.乙個字串可以看成它自身的摺疊。記作s s 2.x s 是x x 1 個s連線在一起的串的摺疊。記作x s ssss s x個s 3.如果a a b b 則ab a b 例如,因為3 a aaa,2 b bb,所以3 a c2 b aaacbb,而2 3 a c 2 b ...
bzoj1090(區間dp,字串摺疊問題)
這個問題比上乙個簡單一點,應該對比一下兩題的相似與不同點,來找到解題的技巧 這題是用遞推實現的,不用記憶化。f l r 表示,把l r這個區間摺疊的最短長度,然後我們想,對於乙個區間來說,我們有兩種選擇,一種是把這個區間它自己來摺疊,另一種是兩塊已經摺疊的區間接起來。對於第二中情況,直接列舉斷點 兩...
1090 SCOI2003 字串摺疊
題目鏈結 題目大意 摺疊的定義如下 1.乙個字串可以看成它自身的摺疊。2.x s 是x x 1 個s連線在一起的串的摺疊,記作x s 3.摺疊可以巢狀。給乙個字串,求它的最短摺疊。題解 區間dp f l r 表示 l r 壓縮後最短長度,初始值f l r r l 1 轉移 列舉區間分割點k,l k ...